连通分量___刷题记录

hdu 1269

判断是否存在一个强连通

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<stack>
 6 #include<vector>
 7 using namespace std;
 8
 9 const int maxn = 10005;
10 vector<int> g[maxn];
11 stack<int> S;
12
13 int n,m;
14 int sccno[maxn],low[maxn],pre[maxn];
15 int scc_cnt,dfs_clock;
16
17 void init(){
18     while(!S.empty()) S.pop();
19     for(int i = 1;i <= n;i++) g[i].clear();
20     scc_cnt = dfs_clock = 0;
21     memset(sccno,0,sizeof(sccno));
22     memset(low,0,sizeof(low));
23     memset(pre,0,sizeof(pre));
24 }
25
26 void dfs(int u){
27     low[u] = pre[u] = ++dfs_clock;
28     S.push(u);
29     for(int i = 0;i < g[u].size();i++){
30         int v = g[u][i];
31         if(!pre[v]){
32             dfs(v);
33             low[u] = min(low[v],low[u]);
34         }
35         else if(!sccno[v]) low[u] = min(low[u],pre[v]);
36     }
37     if(low[u] == pre[u]){
38         scc_cnt++;
39         for(;;){
40             int x = S.top();S.pop();
41             sccno[x] = scc_cnt;
42             if(x == u) break;
43         }
44     }
45 }
46
47 void find_scc(){
48     for(int i = 1;i <= n;i++){
49         if(!pre[i]) dfs(i);
50     }
51     if(scc_cnt == 1) printf("Yes\n");
52     else printf("No\n");
53 }
54
55 int main(){
56     while(scanf("%d %d",&n,&m) != EOF && (n ||m)){
57         init();
58         for(int i = 0;i < m;i++){
59             int u,v;
60             scanf("%d %d",&u,&v);
61             g[u].push_back(v);
62         }
63         find_scc();
64     }
65     return 0;
66 }

la 4287

白书上的例题

给一张图,问最少需要添加多少条边变成强连通

先求一遍强连通,然后把每一个强连通分量缩成一个点,再扫一遍边,如果发现一条边的两端u,v属于不同的强连通分量,如果是u--->v,那么in[scc[v]]++,out[scc[u]++;

最后统计入度为0的强连通分量个数a,出度为0的b,max(a,b)即为添加的最少边数

因为对于一个强连通,每一个点的入度至少为1.出度也至少为1,添加max(a,b)条边,能够满足这个条件

----不知道为什么用vector存图写的wa了,换成邻接表就过了

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<stack>
  6 using namespace std;
  7
  8 const int maxn = 20005;
  9 int first[maxn];
 10 int low[maxn],pre[maxn],sc[maxn];
 11 int din[maxn],dout[maxn];
 12 int n,m;
 13 int ecnt,scnt,dfs_clock;
 14 stack<int> S;
 15
 16 struct Edge{
 17     int v,next;
 18 }e[3*maxn];
 19
 20 void init(){
 21     ecnt = 0;
 22     memset(first,-1,sizeof(first));
 23     memset(din,0,sizeof(din));
 24     memset(dout,0,sizeof(dout));
 25 }
 26
 27 void addedges(int u,int v){
 28     e[ecnt].v = v;
 29     e[ecnt].next = first[u];
 30     first[u] = ecnt++;
 31 }
 32
 33 void dfs(int u){
 34     low[u] = pre[u] = ++dfs_clock;
 35     S.push(u);
 36     for(int i = first[u];~i;i = e[i].next){
 37         int v = e[i].v;
 38         if(!pre[v]){
 39             dfs(v);
 40             low[u] = min(low[u],low[v]);
 41         }
 42         else if(!sc[v]) low[u] = min(low[u],pre[v]);
 43     }
 44     if(pre[u] == low[u]){
 45         scnt++;
 46         for(;;){
 47             int x = S.top();S.pop();
 48             sc[x] = scnt;
 49             if(x == u) break;
 50         }
 51     }
 52 }
 53
 54 void find_scc(){
 55     while(!S.empty()) S.pop();
 56     memset(low,0,sizeof(low));memset(pre,0,sizeof(pre));
 57     memset(sc,0,sizeof(sc));
 58     dfs_clock = scnt = 0;
 59     for(int i = 1;i <= n;i++) if(!pre[i]) dfs(i);
 60 }
 61
 62 int main(){
 63     int T;
 64     scanf("%d",&T);
 65     while(T--){
 66         scanf("%d %d",&n,&m);
 67         init();
 68         for(int i = 1;i <= m;i++){
 69             int u,v;
 70             scanf("%d %d",&u,&v);
 71             addedges(u,v);
 72         }
 73         find_scc();
 74         if(scnt == 1){
 75             printf("0\n");
 76             continue;
 77         }
 78         for(int u = 1;u <= n;u++){
 79             for(int i = first[u];~i;i = e[i].next){
 80                 int v = e[i].v;
 81                 if(sc[u] != sc[v]){
 82                     din[sc[v]]++;
 83                     dout[sc[u]]++;
 84                 }
 85             }
 86         }
 87
 88     //    printf("scnt = %d\n",scnt);
 89     //    for(int i = 1;i <= scnt;i++)
 90     //    printf("din[%d] = %d  dout[%d] = %d\n",i,din[i],i,dout[i]);
 91
 92         int a = 0,b = 0;
 93         for(int i = 1;i <= scnt;i++){
 94             if(din[i] == 0) a++;
 95             if(dout[i] == 0) b++;
 96         }
 97         printf("%d\n",max(a,b));
 98     }
 99     return 0;
100 }

时间: 2024-10-02 14:20:25

连通分量___刷题记录的相关文章

BZOJ 刷题记录 PART 4

[BZOJ1143]CTSC的题目...先用floyed传递闭包,然后直接上匈牙利算法. [BZOJ1452]从未写过的二维树状数组.好像很简单.. struct two_bit { int f[305][305]; inline void add(int x,int z,int A) { for (;x<=n;x+=L(x)) for (int y=z;y<=m;y+=L(y)) f[x][y]+=A; } inline int ask(int x,int z) { int ans=0; f

[2015.6.28] OI刷题记录

FZSZOJ刷题记录: 1051 砝码称重: DP 多重背包 1058 liqeuer: 序列DP 1061 挖地雷:DP,注意需要倒过来做DP,同时记录路径. 1059 Number:DP 1054 数塔问题:同数字三角形,普通DP 1390 等式问题:爆搜,枚举每个+号或-号的位置 1006 中位数:维护大根堆+小根堆,每次插入调整 1005 Cube Stacking:并查集维护当前在第几个和当前集合的高度,并查集变种. 1073 DNA分子的最佳比对:序列DP 1110 奖学金:傻逼题,

首师大附中科创教育平台 我的刷题记录(3)

首师大附中科创教育平台我的刷题记录(给大家刷11--15题吧) 仅供同学们参考,禁止抄袭!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #include<iostream> #include<math.h> using namespace std; int main() { int x,y; cin>>x; y=abs(x+2); cout<<x*x-y+5<<endl; return 0; } 绝对值函数 #include

BZOJ 刷题记录 PART 5

拖了好久才写的. [BZOJ2821]接触分块大法.这道题略有点新颖.首先我们先分块,然后统计每块中每个数出现的个数. 下面是联立各个方块,预处理出第I个方块到第J个方块出现正偶数次数的个数. for (i=1;i<=s;i++) { for (j=i;j<=s;j++) { sum[i][j]=sum[i][j-1]; for (k=a[j].l;k<=a[j].r;k++) { temp[data[k]]++; if (!(temp[data[k]]&1)) sum[i][j

首师大附中科创教育平台 我的刷题记录(7)

首师大附中科创教育平台我的刷题记录(这次给大家刷多一点,31--40题吧) 仅供同学们参考,禁止抄袭!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #include<iostream> using namespace std; int main() { int n; cin>>n; if(n%4==0&&n%100!=0||n%400==0) cout<<"yes"<<endl; else cout&

首师大附中科创教育平台 我的刷题记录(6)

首师大附中科创教育平台我的刷题记录(给大家刷26--30题吧) 仅供同学们参考,禁止抄袭!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #include<iostream> #include<math.h> using namespace std; int main() { double I,R,r,E; cin>>I>>R>>r; E=I*(R+r); cout<<E<<endl; return 0

首师大附中科创教育平台 我的刷题记录 0284 最强大脑

从现在开始,我的刷题记录都开始给大家一个一个刷!今天给大家献上“E”级题:最强大脑!! 试题编号:0284     最强大脑 难度级别:E: 运行时间限制:3000ms: 运行空间限制:256000KB: 代码长度限制:2000000B 试题描述 zhb国是一个传说中的国度,国家的居民叫做最强(chang)大脑(diao).Zhb国是一个N×M的矩形方阵,每个格子代表一个街区.然而zhb国是没有交通工具的.居民大脑(diao)们完全靠地面的弹射装置来移动.每个街区都装有弹射装置.使用弹射装置是需

首师大附中科创教育平台 我的刷题记录(5)

首师大附中科创教育平台我的刷题记录(给大家刷21--25题吧) 仅供同学们参考,禁止抄袭!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #include<iostream> #include<math.h> using namespace std; int main() { double a,b,x; cin>>a>>b; x=-b/a; cout<<x<<endl; return 0; } 一元一次方程 #in

BZOJ 刷题记录 PART 1

作者 : Dolphin 原文地址:http://blog.csdn.net/qingdujun/article/details/27109035 一.实体完整性定义 [例1]将Student表中的Sno属性定义为码. CREATE TABLE Student ( Sno CHAR(10) PRIMARY KEY, /*在列定义主码*/ Sname CHAR(20) NOT NULL, Sage SMALLINT ); 或者: CREATE TABLE Student ( Sno CHAR(10