zoukankan      html  css  js  c++  java
  • CodeForces 506B/505D Mr. Kitayuta's Technology

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

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

    好题

    给n个城市,m条有向边,求出最少的有向边使得其构成的图与原图等势

    对于每个连通分量:

    如果无环,那么只需要需要n-1条边完成联通

    如果有环,则只需要n条边完成联通

    所以这题只要判下连通分量,再看有几个连通分量有环即可

    解法一:无向图遍历求强连通分量再把强连通分量所代表的联通分量dfs判环,如下

    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好

    解法二:在无向图中维护并查集求强连通分量再把强连通分量所代表的联通分量用拓扑排序判环,如下

    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

    其实求连通分量还可以用染色

      判有向环可以用并查集乱搞

    反正就是怎么搞都能过

  • 相关阅读:
    【Vegas原创】解决System.Web.Extensions版本冲突方法
    【Vegas原创】GridView修改表头,并导出Excel(C#版)
    bdump,cdump,udump作用
    【Vegas原创】用正则表达式解决FCKEditor图片路径问题
    【Vegas改编】获取,更新web.config的值
    面向对象和面向过程的区别
    【Vegas原创】删除有内外键关系数据的方法
    提供css滤镜代码,变网页为黑白,为在地震中遇难的同胞哀悼
    【Vegas原创】将treeview父结点的链接改为折叠事件
    C#经典试题
  • 原文地址:https://www.cnblogs.com/mukoiaoi/p/5655796.html
Copyright © 2011-2022 走看看