日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

清北学堂Day4

發(fā)布時間:2023/12/18 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 清北学堂Day4 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?

(1)第一題

財富(treasure)

Time Limit:1000ms?? Memory Limit:128MB

題目描述

LYK有n個小伙伴。每個小伙伴有一個身高hi。

這個游戲是這樣的,LYK生活的環(huán)境是以身高為美的環(huán)境,因此在這里的每個人都羨慕比自己身高高的人,而每個人都有一個屬性ai表示它對身高的羨慕值。

這n個小伙伴站成一列,我們用hi來表示它的身高,用ai來表示它的財富。

每個人向它的兩邊望去,在左邊找到一個最近的比自己高的人,然后將ai朵玫瑰給那個人,在右邊也找到一個最近的比自己高的人,再將ai朵玫瑰給那個人。當然如果沒有比自己身高高的人就不需要贈送別人玫瑰了。也就是說一個人會給0,1,2個人玫瑰(這取決于兩邊是否有比自己高的人)。

每個人都會得到若干朵玫瑰(可能是0朵),LYK想知道得了最多的玫瑰的那個人得了多少玫瑰。(然后嫁給他>3<)

輸入格式(treasure.in)

??? 第一行一個數(shù)n表示有n個人。

??? 接下來n行,每行兩個數(shù)hi,ai。

輸出格式(treasure.out)

??? 一個數(shù)表示答案。

輸入樣例

3

4 7

3 5

6 10

輸出樣例

12

樣例解釋

第一個人會收到5朵玫瑰,第二個沒人送他玫瑰,第三個人會收到12朵玫瑰。

數(shù)據(jù)范圍

對于50%的數(shù)據(jù)n<=1000,hi<=1000000000。

對于另外20%的數(shù)據(jù)n<=50000,hi<=10。

對于100%的數(shù)據(jù)1<=n<=50000,1<=hi<=1000000000。1<=ai<=10000。

這道題從某種程度上來說是道一眼題。因為一眼就能看出O(n^2)的做法。但作為一個有追求的人,我還是認真的思考了一下有沒有O(n)的辦法,畢竟O(n^2)估計不能A。但后來也沒想出來,所以就……嗯。

我的代碼(沒想到竟然拿滿了,大概是數(shù)據(jù)有點弱):

1 #include <iostream> 2 #include <cmath> 3 #include <cstring> 4 #include <cstdio> 5 #include <cstdlib> 6 #include <algorithm> 7 using namespace std; 8 long long a[50101],h[50101]; 9 long long sum[50101]; 10 int main() 11 { 12 13 freopen("treasure.in","r",stdin); 14 freopen("treasure.out","w",stdout); 15 16 int n; 17 scanf("%d",&n); 18 long long minn=1000000005,maxn=0; 19 for(int i=1;i<=n;i++) 20 { 21 scanf("%lld%lld",&h[i],&a[i]); 22 minn=min(minn,h[i]); 23 maxn=max(maxn,h[i]); 24 } 25 for(int i=1;i<=n;i++) 26 { 27 if(a[i]==maxn) continue; 28 if(a[i]==minn) {sum[i-1]+=a[i];sum[i+1]+=a[i];continue;} 29 for(int j=i-1;j>0;j--) 30 { 31 if(h[j]>h[i]) {sum[j]+=a[i];break;} 32 } 33 for(int j=i+1;j<=n;j++) 34 { 35 if(h[j]>h[i]) {sum[j]+=a[i];break;} 36 } 37 } 38 long long ans=0; 39 for(int i=1;i<=n;i++) ans=max(ans,sum[i]); 40 printf("%lld",ans); 41 //system("pause"); 42 return 0; 43 } a

后來老師講了O(n)的做法。然而好像有點沒聽懂……代碼如下 : ?@周老師

1 #include <cmath> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 int n,s[50002],d[50002],ans[50002],ANS,a[50002],b[50002],r,i; 8 //b[i]表示第i個人收到的玫瑰數(shù) 9 //s[]單調(diào)隊列 10 //d[i]在單調(diào)的數(shù)列中第i個位置是n個人中的哪個人 11 int main() 12 { 13 freopen("treasure.in","r",stdin); 14 freopen("treasure.out","w",stdout); 15 cin>>n; 16 for (i=1; i<=n; i++) scanf("%d%d",&a[i],&b[i]); 17 s[1]=a[1]; d[1]=1; r=1; 18 for (i=2; i<=n; i++) 19 { 20 while (r!=0 && a[i]>s[r]) {ans[i]+=b[d[r]]; r--; } 21 r++; //隊列中元素+1 22 s[r]=a[i];//推入單調(diào)隊列 23 d[r]=i; 24 } 25 s[1]=a[n]; d[1]=n; r=1; 26 for (i=n-1; i>=1; i--) 27 { 28 while (r!=0 && a[i]>s[r]) { ans[i]+=b[d[r]]; r--; } 29 r++; 30 s[r]=a[i]; 31 d[r]=i; 32 } 33 for (i=1; i<=n; i++) ANS=max(ANS,ans[i]); 34 cout<<ANS; 35 return 0; 36 } astd

(2)第二題

正方形(square)

Time Limit:1000ms?? Memory Limit:128MB

題目描述

在一個10000*10000的二維平面上,有n顆糖果。

LYK喜歡吃糖果!并且它給自己立了規(guī)定,一定要吃其中的至少C顆糖果!

事與愿違,LYK只被允許圈出一個正方形,它只能吃在正方形里面的糖果。并且它需要支付正方形邊長的價錢。

LYK為了滿足自己的求食欲,它不得不花錢來圈一個正方形,但它想花的錢盡可能少,你能幫幫它嗎?

輸入格式(square.in)

??? 第一行兩個數(shù)C和n。

??? 接下來n行,每行兩個數(shù)xi,yi表示糖果的坐標。

輸出格式(square.out)

??? 一個數(shù)表示答案。

輸入樣例

3 4

1 2

2 1

4 1

5 2

輸出樣例

4

樣例解釋

選擇左上角在(1,1),右下角在(4,4)的正方形,邊長為4。

數(shù)據(jù)范圍

對于30%的數(shù)據(jù)n<=10。

對于50%的數(shù)據(jù)n<=50。

對于80%的數(shù)據(jù)n<=300。

對于100%的數(shù)據(jù)n<=1000。1<=xi,yi<=10000。

我就是兩兩的枚舉端點,然后用這兩個端點擴出一個最小的正方形,之后搜一遍里面有多少點。如果點數(shù)夠了,就與當前的ans比較,保留小的。但是只過了兩個點,其他的都結(jié)果錯誤。可能是因為我默認正方形的左上角(或右上角)有一顆糖框住,但其實不一定。

我的代碼:

1 #include <iostream> 2 #include <cmath> 3 #include <cstring> 4 #include <cstdio> 5 #include <cstdlib> 6 #include <algorithm> 7 using namespace std; 8 int n,C; 9 int xz,yz,xy,yy; 10 int maxn; 11 struct point 12 { 13 int x,y; 14 bool operator <(const point&o)const 15 { 16 if(x<o.x) return true; 17 else if(x==o.x && y<o.y) return true; 18 else return false; 19 } 20 }a[1010]; 21 void make_square(int i,int j) 22 { 23 maxn=0; 24 maxn=max(abs(a[j].y-a[i].y)+1,abs(a[j].x-a[i].x)+1); 25 //cout<<maxn<<endl; 26 if(a[i].y<=a[j].y) {xz=a[i].x;yz=a[i].y;xy=xz+maxn-1;yy=yz+maxn-1;} 27 else 28 { 29 xz=a[i].x;yz=a[i].y-maxn+1; 30 xy=a[i].x+maxn-1;yy=a[i].y; 31 } 32 } 33 bool check() 34 { 35 int cnt=0; 36 for(int i=1;i<=n;i++) 37 { 38 if(a[i].x>=xz && a[i].x<=xy && a[i].y>=yz && a[i].y<=yy) cnt++; 39 if(cnt>=C) break; 40 } 41 if(cnt>=C) return true; 42 else return false; 43 } 44 45 int main() 46 { 47 freopen("square.in","r",stdin); 48 freopen("square.out","w",stdout); 49 scanf("%d%d",&C,&n); 50 for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y); 51 sort(a+1,a+n+1); 52 //for(int i=1;i<=n;i++) cout<<a[i].x<<" "<<a[i].y<<endl; 53 int ans=10005; 54 for(int i=1;i<n;i++) 55 { 56 for(int j=i+1;j<=n;j++) 57 { 58 make_square(i,j); 59 if(check()) ans=min(ans,maxn); 60 } 61 } 62 printf("%d",ans); 63 //system("pause"); 64 return 0; 65 } b

正解思路:

1.正方形的上、下、左、右一定有和糖果貼在一起的。不然會浪費。

因此我們可以枚舉上下左,之后找一個合適的右邊。最后再把這個長方形擴成正方形。

------------------------------插播:離散化---------------------------

1 Struct node{int x,y;}t[10005]; 2 In cmp(node I,node j) {i.y<j.y;} 3 4 For(int i=1;i<=n;i++) cin>>a[i]; 5 For(int i=1;i<=n;i++) t[i].x=I,t[i].y=a[i]; 6 Sort(t+1,t+n+1,cmp); 7 For(int i=1;i<=n;i++) 8 { 9 If(t[i].y!=t[i-1].y) now++; 10 P[now]=a[t[i],x]; 11 A[t[i].x]=now; 12 }

【例子】:

離散前:3 3 1 5

離散后:2 2 1 3

由此可見,離散化的作用是縮小空間。正好適用于這道題(由原來的10000*10000變?yōu)閚*n的大小,二維空間大大縮小)

--------------------------------插播結(jié)束--------------------------------

算法改進:枚舉上邊和下邊。左邊為1的情況下,右邊是什么隨著左邊向右移動,右邊也一定向右移動。

左邊至多移動n次,右邊也至多移動n次,總共2n次

O(n^3)

繼續(xù)改進:

我們發(fā)現(xiàn),本題答案是連續(xù)的。即,如果邊長為x可行,邊長為x+1也可行(至少覆蓋C個糖果);假如x不可行,x-1也不可行。

由此可知,我們可以二分答案

L,r判斷mid是否可行 --->正常的二分

之后,

枚舉上邊在哪里,下邊的位置是固定的。哪些糖果被夾在這段區(qū)間中? O(n)

再之后

左邊為1的情況下,右邊是什么

隨著左邊向右移動,右邊也一定向右移動。

左邊至多移動n次,右邊也至多移動n次,總共2n次?? O(n)

?

P.s:也可以用前綴和來做

標程:

1 #include <cmath> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 struct node {int x,y;} a[1005]; 8 int C,n,L,R,mid,b[1005],o,i; 9 int cmp(node i,node j) {return i.x<j.x;} 10 int CMP(int i,int j) {return i<j;} 11 bool WORK(int l,int r) 12 { 13 if (r-l+1<C) return false; o=0; 14 for (int i=l; i<=r; i++) b[++o]=a[i].y; 15 sort(b+1,b+o+1,CMP); 16 for (int i=C; i<=o; i++) 17 if (b[i]-b[i-C+1]<=mid) return true; 18 return false; 19 } 20 bool OK(int x) 21 { 22 int l=1; 23 for (int i=1; i<=n; i++) //枚舉上邊 24 { 25 if (a[i].x-a[l].x>x) 26 { 27 if (WORK(l,i-1)) return true; 28 while (a[i].x-a[l].x>x) l++; 29 } 30 } 31 if (WORK(l,n)) return true; 32 return false; 33 } 34 int main() 35 { 36 freopen("square.in","r",stdin); 37 freopen("square.out","w",stdout); 38 scanf("%d%d",&C,&n); 39 for (i=1; i<=n; i++) 40 scanf("%d%d",&a[i].x,&a[i].y); 41 sort(a+1,a+n+1,cmp); 42 L=0; R=10000; mid=(L+R)/2; 43 while (L<=R) //二分答案 44 { 45 if (OK(mid)) {R=mid-1; mid=(L+R)/2;} else 46 { 47 L=mid+1; 48 mid=(L+R)/2; 49 } 50 } 51 cout<<L+1; 52 return 0; 53 } bstd

(3)第三題這是不是我第一次決定把第三題也寫下來...

追逐(chase)

Time Limit:1000ms?? Memory Limit:128MB

題目描述

這次,LYK以一個上帝視角在看豹子賽跑。

在一條無線長的跑道上,有n只豹子站在原點。第i只豹子將在第ti個時刻開始奔跑,它的速度是vi/時刻。

因此在不同的時刻,這n只豹子可能在不同的位置,并且它們兩兩之間的距離也將發(fā)生變化。

LYK覺得眼光八方太累了,因此它想找這么一個時刻,使得最遠的兩只豹子的距離盡可能近,當然這不能是第0時刻或者第0.01時刻。它想知道的是最遲出發(fā)的豹子出發(fā)的那一刻開始,離得最遠的兩只豹子在距離最小的時候這個距離是多少。

當然這個時刻不僅僅可能發(fā)生在整數(shù)時刻,也就是說可能在1.2345時刻這個距離最小。

輸入格式(chase.in)

??? 第一行一個數(shù)n。

??? 接下來n行,每行兩個數(shù)分別是ti和vi。

輸出格式(chase.out)

??? 輸出一個數(shù)表示答案,你只需保留小數(shù)點后兩位有效數(shù)字就可以了。

輸入樣例

3

1 4

2 5

3 7

輸出樣例

0.33

樣例解釋

在第5+2/3這個時刻,第一只豹子在18+2/3這個位置,第二只豹子在18+1/3這個位置,第三只豹子在18+2/3這個位置,最遠的兩只豹子相距1/3的距離,因此答案是0.33。

數(shù)據(jù)范圍

對于20%的數(shù)據(jù)n=2。

對于20%的數(shù)據(jù)n=3

對于60%的數(shù)據(jù)n<=100。

對于80%的數(shù)據(jù)n<=1000。

對于100%的數(shù)據(jù)n<=100000,1<=vi,ti<=100000。

這道題本來是棄了,后來發(fā)現(xiàn)20%還是很好寫的。然后就寫了一下。結(jié)果迷之運行時錯誤。(所以代碼就不放了)

正解思路:

假如一條直線代表一只豹砸

?

可以分別描出每一時刻離原點最近和最遠的豹砸

?

綠色部分就是他們的差,題目要求找的就是最短的綠線。

易證綠色的只會在交點處最小

60分算法:求出所有交點,然后再求每只豹砸

?

?

排除掉跑得慢又跑的晚的豹子后,我們發(fā)現(xiàn)斜率大的豹子占據(jù)右邊一段

用單調(diào)棧實現(xiàn)

?

如圖,三條斜率不同的線段最后的上凸殼是紫色部分。也就是說,在這種情況下,每遇到一個交點上凸殼方向就會改變。

?

下凸殼同理:對于兩只豹子,一只跑得慢且后跑,一只跑得快一開始就跑。我們保留前面那只。

上凸殼流程:

  • 插入一條線,把所有值都先賦給第一條線;
  • 插入第二條線,把向上拐的那一段交給第二條線保管(也就是縫交點變保管線段)
  • 以此類推…
  • 標程(可以說是很可怕了):

    1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<iostream> 6 #include<algorithm> 7 8 using namespace std; 9 const long double INF=(long double)1000000000*10; 10 long double L,R,mid,ans,hh[100005]; 11 int r,rr,i,n,MAX,X,Y,cnt,vv[100005],vv2[100005]; 12 struct node2 {int t; long double l;} s[200005],S[200005]; 13 struct node {int t,v;} t[100005]; 14 int cmp(node i,node j) {return i.v<j.v || i.v==j.v && i.t>j.t;} 15 struct Node {long double x;int y,z;} p[200005]; 16 int CMP(Node i,Node j) {return i.x<j.x;} 17 long double work(int x,long double y) {return (long double)t[x].v*y-hh[x];} 18 int main() 19 { 20 freopen("chase.in","r",stdin); 21 freopen("chase.out","w",stdout); 22 while (1) 23 { 24 scanf("%d",&n); 25 // if (n==0) return 0; 26 MAX=0; 27 for (i=1; i<=n; i++) 28 { 29 scanf("%d%d",&t[i].t,&t[i].v); 30 MAX=max(MAX,t[i].t); 31 } 32 sort(t+1,t+n+1,cmp); int MIN=t[n].t; 33 for (i=n-1; i>=2; i--) 34 { 35 if (t[i].t>MIN) vv[i]=1; else 36 MIN=t[i].t,vv[i]=0; 37 } 38 for (i=1; i<=n; i++) hh[i]=(long double)t[i].t*t[i].v; 39 r=1; s[1].l=MAX; s[1].t=1; s[2].l=INF; vv[n]=0; 40 for (i=2; i<=n; i++) 41 if (!vv[i]) 42 { 43 while (r && work(i,s[r].l)>=work(s[r].t,s[r].l)) r--; 44 if (!r) {r=1; s[1].l=MAX; s[1].t=i; continue;} 45 L=s[r].l; R=s[r+1].l; mid=(L+R)/2.0; 46 for (int I=1; I<=80; I++) 47 { 48 if (work(i,mid)>=work(s[r].t,mid)) {R=mid; mid=(L+R)/2.0;} else {L=mid; mid=(L+R)/2.0;} 49 } 50 s[++r].l=mid; s[r].t=i; s[r+1].l=INF; 51 } 52 rr=1; S[1].l=MAX; S[2].l=INF; S[1].t=n; 53 MIN=t[1].t; 54 for (i=2; i<n; i++) 55 if (t[i].t<MIN) vv2[i]=1; else 56 MIN=t[i].t,vv2[i]=0; 57 for (i=n-1; i>=1; i--) 58 if (!vv2[i]) 59 { 60 while (rr && work(i,S[rr].l)<=work(S[rr].t,S[rr].l)) rr--; 61 if (!rr) {rr=1; S[1].l=MAX; S[1].t=i; continue;} 62 L=S[rr].l; R=S[rr+1].l; mid=(L+R)/2.0; 63 for (int I=1; I<=80; I++) 64 { 65 if (work(i,mid)<=work(S[rr].t,mid)) {R=mid; mid=(L+R)/2.0;} else {L=mid; mid=(L+R)/2.0;} 66 } 67 S[++rr].l=mid; S[rr].t=i; S[rr+1].l=INF; 68 } 69 cnt=0; 70 for (i=1; i<=r; i++) {p[++cnt].x=s[i].l; p[cnt].y=1; p[cnt].z=s[i].t;} 71 for (i=1; i<=rr; i++) {p[++cnt].x=S[i].l; p[cnt].y=0; p[cnt].z=S[i].t;} 72 sort(p+1,p+cnt+1,CMP); X=Y=0; ans=INF; //X是上凸指針Y是下凸指針 73 for (i=1; i<=cnt; i++) //遇到上凸X動,遇到下凸Y動 74 { 75 if (p[i].y==1) X=p[i].z; else Y=p[i].z; 76 // printf("%.5f\n",(double)p[i].x); 77 if (X && Y) ans=min(ans,work(X,p[i].x)-work(Y,p[i].x)); 78 } 79 printf("%.2f\n",fabs((double)ans)); 80 return 0; 81 } 82 } cstd

    今日專題——圖論

    圖論

    ??????????????????????????? ——算法簡單,難點在于構(gòu)圖

    l? 競賽圖:任意兩個人(點)打一場比賽,由贏的向輸?shù)倪B一條邊。

    l? 鄰接表的實現(xiàn):

    cin>>u>>v; (u->v)

    f[u][++f[u][0]]=v;

    ?

    f[u][0]表示u連出去能到幾個點

    f[u][i]表示u連出去第i個點是啥

    ?

    l? 鄰接表的好處:在遍歷一個點能連向哪些點時,復雜度是出度,而不是O(n)

    l? 鄰接矩陣的好處:判斷一條邊是否存在,查詢一條邊的權值,復雜度是O(1)

    l? 邊表(前向星):

    cin>>u>>v;

    o++;

    e[o]=v;? (u->v)? 之前u還指向過一些點 head[u]來表示起點為u的邊編號最大的那個編號是多少

    next[o]=head[o]?? 當u處理完連向v的這條邊之后,下一次處理的邊編號是多少

    head[u]=o;

    ?

    便利u為起點,能連向哪些點

    For(int i=head[u];i!=0;)

    ?

    l? 拓撲排序

    給定一張拓撲圖,求1號點走到n號點的方案總數(shù)

    ?

    令dp[i]表示從1號點走到i號點的方案總數(shù)

    有dp[i]=xigma(dp[j]) (j->i)

    枚舉i時,按照拓撲序進行枚舉

    Dp[n]就是答案

    ?

    l? 最短路

  • Dijkstra
  • (1)令dis[i]表示當前u到i的最短路是多少。

    (2)將dis[u]=0,dis[i]=inf(i!=u)。

    (3)尋找最小的dis[x]且x曾經(jīng)沒被找到過。

    (4)若x=v,輸出答案并退出。

    (5)枚舉x的所有邊,用dis[x]去更新其余dis[],回到步驟②。

    時間復雜度為n^2。

    使用范圍:不存在負權邊。

    2. SPFA(poj1502)

  • 令dis[i]表示當前u到i的最短路是多少。
  • ①將dis[u]=0,dis[i]=inf(i!=u),并將u加入隊列中。
  • ②設當前隊首為x,枚舉x。
  • ③枚舉x的所有邊,用dis[x]去更新其余dis[],若dis[i]此時被更新且i當前不在隊列中,將其加入隊列。
  • ④將x彈出隊列,若此時隊列為空,結(jié)束,否則返回步驟②。
  • ?

    l? 并查集

    ?

    一行并查集(實現(xiàn)了路徑壓縮):

    Int getf(int x) {return f[x]=x?f[x]:f[x]=getf(f[x]);}?? //不斷找father

    ?

    l? 最小生成樹

    1.Prim:一開始隨便找一個點當做集合中點,每次找一條最短的邊,要求這條邊鏈接的兩個點,一個在集合中,一個不在集合中。把連接的另一個點和這條邊加入到集合中。

    2.kruskal:對邊權進行排序,每次加入后判斷是否存在環(huán),若不存在環(huán),則加入(并查集實現(xiàn))

    ?

    l? 二分圖(不存在奇環(huán),即有奇數(shù)個點的環(huán))

    二分圖染色:(col[i]=1->i這個點染成黑色 col[i]=2->i這個點染成白色 col[i]=0->i這個點還未被染色)

    Vector <int> v[N];

    Void dfs(int x,int y)

    {

    Col[x]=y;

    For(int i=0;i<v[x].size();i++)

    {

    ??? If(!col[v[x][i]]) dfs(v[x][i],3-y);

    If(col[v[x][i]]==col[x]) FLAG=true;? //如果一條邊連接的兩個點是同一種顏色,這是不被允許的(判定方法1)

    }

    }

    For(int i=1;i<=n;i++) col[i]=0;

    For(int i=1;i<=n;i++) if(!col[i])dfs(i,1);

    if(FLAG) cout<<’no’; else cout<<’yes’;

    二分圖判定方法2

    • 將每個點A裂成兩個點A與A’。
    • 若A與B之間存在邊,則連一條A與B’的邊,A’與B的邊。
    • 若此時A與A’連通,或者B與B’連通,則該圖不是二分圖。(若連通則必然出現(xiàn)了奇環(huán))
    • 利用并查集實現(xiàn)即可。

    ?

    ?

    [圖例解釋]標記完成后,若發(fā)現(xiàn)2與2`連通了,則不是二分圖(奇環(huán))

    可通過染色來理解,會出現(xiàn)矛盾

    For(int i=1;i<=n;i++) p[i][0]=++cnt,p[i][1]=++cnt;

    For(int i=2;i<=cnt;i++) f[i]=I;

    For(int i=1;i<=m;i++)

    {

    u-v

    f[getf(p[u][0])]=getf(p[v][1]);

    f[getf(p[u][1])=getf(p[v][0]);

    if(getf(p[u][0])==getf(p[u][1])||getf(p[v][0])==getf(p[v][1]))FLAG=true;

    }

    l? 二分圖最大匹配

    匈牙利算法:

    ?

    ?

    l? 強連通分量:任意兩個點之間相互可達

    l? DPN時間戳(第幾次被DFS到)

    l? ***LOW LOW[i] i及i的所有子孫能訪問到的最小時間戳

    ?

    求極大強連通分量(Tarjan):

    Void dfs(int x)

    {

    DFN[x]=++Time;Low[x]=DFN[x];

    St[++r]=x; /*壓入棧*/int R=r; V[x]=true;

    For(int i=0;i<v[x].size();i++) //枚舉x能連向哪些點

    {

    ?if(!DFN[v[x][i]]){dfs(v[x][i]);LOW[x]=min(LOW[x],LOW[v[x][i]]);}? //如果當前點還沒dfs過,就dfs一遍。同時更新時間戳

    ???? if(V[v[x][i]])LOW[x]=min(LOW[x],DFN[v[x][i]]);

    }

    If(LOW[x]==DFN[x])

    {

    cnt++;

    ??? For(int i=R;i<=r;i++) p[st[i]]

    r=R-1;

    }

    }

    cnt 第cnt個強連通分量??? p[i] i所處的的事哪個極大強連通分量

    LOW[x]==DFN[x] 已出現(xiàn)一個極大強連通分量

    ?

    **背代碼最開始每天都要默一遍**

    ?

    今天信息量簡直太大,腦袋要炸掉了。。

    轉(zhuǎn)載于:https://www.cnblogs.com/lulala/p/7627061.html

    總結(jié)

    以上是生活随笔為你收集整理的清北学堂Day4的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。