CodeForces 506B/505D Mr. Kitayuta's Technology

Portal:http://codeforces.com/problemset/problem/506/Bios

    http://codeforces.com/problemset/problem/505/D ide

好題函數

給n個城市,m條有向邊,求出最少的有向邊使得其構成的圖與原圖等勢spa

對於每一個連通份量:3d

若是無環,那麼只須要須要n-1條邊完成聯通code

若是有環,則只須要n條邊完成聯通blog

因此這題只要判下連通份量,再看有幾個連通份量有環便可排序

解法一:無向圖遍歷求強連通份量再把強連通份量所表明的聯通份量dfs判環,以下ci

Memory: 10440 KB   Time: 498 MS
 1 #include<iostream>
 2 #include<algorithm>
 3 #include<set>
 4 #include<cstdio>
 5 #include<cstdlib>
 6 #include<cmath>
 7 #include<vector>
 8 using namespace std;
 9 #define FOR(i,j,k) for(int i=j;i<=k;i++)
10 #define FORD(i,j,k) for(int i=j;i>=k;i--)
11 #define LL long long
12 #define SZ(x) int(x.size())
13 #define maxn 100010
14 int n,m,x,y;
15 bool  circle=true;
16 int vis[maxn],vis2[maxn];
17 vector<int> neg[maxn],adj[maxn];
18 vector<int> dot;
19 void ndfs(int start)
20 {
21     dot.push_back(start);
22     vis[start]=1;
23     FOR(i,0,SZ(neg[start])-1)
24     {
25         if(!vis[neg[start][i]]) ndfs(neg[start][i]);
26         
27     }
28     return;
29 }
30 void adfs(int start)
31 {
32     vis2[start]=1;
33     FOR(i,0,SZ(adj[start])-1)
34     {
35         if(!vis2[adj[start][i]]) adfs(adj[start][i]); 
36         else if(vis2[adj[start][i]]==1)circle=false; 
37     }
38     vis2[start]=2;
39     return;
40 }
41 int main()
42 {
43 cin>>n>>m;
44 FOR(i,1,m)
45 {
46     cin>>x>>y;
47     neg[x].push_back(y);
48     neg[y].push_back(x);
49     adj[x].push_back(y);
50 }
51 int ans=n;
52 FOR(i,1,n)
53 {
54     circle=1;
55     if(!vis[i]) 
56     {
57     dot.clear(); 
58     ndfs(i);  
59     FOR(i,0,SZ(dot)-1)
60     if (!vis2[dot[i]]) adfs(dot[i]);
61     ans-=circle;
62     }
63 }
64 cout<<ans<<endl;
65 return 0;
66 }
我在想函數名字到底取afs好仍是adfs好

 

解法二:在無向圖中維護並查集求強連通份量再把強連通份量所表明的聯通份量用拓撲排序判環,以下get

Memory: 7820 KB   Time: 514 MS
 1 #include<iostream>
 2 #include<algorithm>
 3 #include<set>
 4 #include<cstdio>
 5 #include<cstdlib>
 6 #include<cmath>
 7 #include<vector>
 8 using namespace std;
 9 #define FOR(i,j,k) for(int i=j;i<=k;i++)
10 #define FORD(i,j,k) for(int i=j;i>=k;i--)
11 #define LL long long
12 #define SZ(x) int(x.size())
13 #define maxn 100010
14 vector<int> G[maxn];
15 int n,m,x,y,T;
16 int father[maxn],val[maxn],circle[maxn],vis[maxn],clock[maxn];
17 int setfind(int x)
18 {
19     int fa=father[x];
20     if(fa==x) return x;
21     else return father[x]=setfind(fa);
22 }
23 void setunion(int x,int y)
24 {
25     int X=setfind(x);
26     int Y=setfind(y);
27     if(X==Y) return;
28     if(val[X]>val[Y]) father[Y]=X;
29     else father[X]=Y;
30     if(val[X]==val[Y]) val[X]++;
31     return;
32 }
33 void dfs(int start)
34 {
35     vis[start]=1;
36     FOR(i,0,SZ(G[start])-1)
37     if(!vis[G[start][i]]) dfs(G[start][i]);
38     clock[start]=++T;
39     return;
40 }
41 int main()
42 {
43 cin>>n>>m;
44 FOR(i,1,n)
45 {father[i]=i;val[i]=1;}
46 FOR(i,1,m)
47 {
48     cin>>x>>y;
49     G[x].push_back(y);
50     setunion(x,y);
51 }
52 FOR(i,1,n)
53 if(!vis[i]) dfs(i);
54 FOR(i,1,n)
55 FOR(j,0,SZ(G[i])-1)
56 if(clock[i]<clock[G[i][j]]) circle[setfind(i)]=1;
57 int ans=n;
58 FOR(i,1,n)
59 if(i==setfind(i))if(!circle[setfind(i)]) ans--;
60 cout<<ans<<endl;
61 return 0;
62 }
Mr. Kitayuta's Black Technology

其實求連通份量還能夠用染色

  判有向環能夠用並查集亂搞

反正就是怎麼搞都能過

相關文章
相關標籤/搜索