POJ1236 Network of Schools

tarjan裸题 
先用tarjan缩点 
然后找出每个连通块的入度和出度 
入度为0的连通块就是taskA需要的和别的连通块连接的数量 
入度和出度为0的连通块中最大值就是需要taskB的添加ans条边可以让全图都是一个强连通块 
如果原先就是强联通块,则特判

 

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<algorithm>
  4 #define inf 0x3f3f3f3f
  5 
  6 using namespace std;
  7 
  8 const int maxn = 200005;
  9 const int maxm = 1000005;
 10 int n, m, tol, top, cnt;
 11 int maxdeep, pos;
 12 int bridge;
 13 int stacksize;
 14 
 15 struct Node {
 16     int v;
 17     int next;
 18     bool vis;
 19 };
 20 
 21 Node edge[4 * maxn];
 22 Node node[2 * maxm];
 23 bool vis[maxn];
 24 int dfn[maxn];
 25 int low[maxn];
 26 int point[maxn];
 27 int stack[maxn];
 28 int head[maxn];
 29 int head2[maxn];
 30 
 31 void init() {
 32     tol = cnt = top = stacksize = 0;
 33     bridge = 0;
 34     memset(dfn, 0, sizeof(dfn));
 35     memset(low, 0, sizeof(low));
 36     memset(head, -1, sizeof(head));
 37     memset(vis, false, sizeof(vis));
 38     memset(point, 0, sizeof(point));
 39 }
 40 
 41 void addnode(int u, int v) {
 42     node[tol].v = v;
 43     node[tol].vis = false;
 44     node[tol].next = head[u];
 45     head[u] = tol++;
 46 }
 47 
 48 void addedge(int u, int v) {
 49     edge[tol].v = v;
 50     edge[tol].next = head[u];
 51     head[u] = tol++;
 52 }
 53 
 54 void dfs(int u) {
 55     int v;
 56     low[u] = dfn[u] = ++cnt;
 57     vis[u] = true;
 58     stack[stacksize++] = u;
 59     for(int i=head[u]; i!=-1; i=node[i].next) {
 60         v=node[i].v;
 61         if(node[i].vis)
 62             continue;
 63         node[i].vis = node[i^1].vis = true;
 64         if(!dfn[v]) {
 65             dfs(v);
 66             low[u] = min(low[u],low[v]);
 67             if(dfn[u] < low[v])
 68                 bridge++;
 69         } else if(vis[v]) {
 70             low[u] = min(low[u], dfn[v]);
 71         }
 72     }
 73     if(dfn[u] == low[u]) {
 74         top++;
 75         int v;
 76         do {
 77             v = stack[--stacksize];
 78             vis[v] = false;
 79             point[v] = top;
 80         } while(v != u);
 81     }
 82 }
 83 
 84 void tarjan() {
 85     for(int u=1; u<=n; u++) {
 86         if(!dfn[u]) {
 87             dfs(u);
 88         }
 89     }
 90 }
 91 
 92 void dfs2(int u, int deep) {
 93     vis[u] = true;
 94     if(deep > maxdeep) {
 95         maxdeep = deep;
 96         pos = u;
 97     }
 98     for(int i=head[u]; i!=-1; i=edge[i].next) {
 99         int v = edge[i].v;
100         if(!vis[v]) {
101             dfs2(v, deep+1);
102         }
103     }
104 }
105 
106 int main() {
107     while(scanf("%d%d",&n, &m) != EOF) {
108         if(n==0 && m==0)
109             break;
110         init();
111         for(int i=1; i<=m; i++) {
112             int u, v;
113             scanf("%d%d", &u, &v);
114             if(u == v)
115                 continue;
116             addnode(u, v);
117             addnode(v, u);
118         }
119         tarjan();
120         memcpy(head2, head, sizeof(head));
121         memset(head, -1, sizeof(head));
122         tol = 0;
123         for(int u=1; u<=n; u++) {
124             for(int i=head2[u]; i!=-1; i=node[i].next) {
125                 int v = node[i].v;
126                 if(point[u] != point[v]) {
127                     addedge(point[u], point[v]);
128                     addedge(point[v], point[u]);
129                 }
130             }
131         }
132 //      for(int i=0; i<tol; i++)
133 //          printf("%d  %d\n",head[i]);
134         maxdeep = pos = 0;
135         memset(vis, false, sizeof(vis));
136         vis[1] = true;
137         dfs2(1, 0);
138         memset(vis, false, sizeof(vis));
139         maxdeep = 0;
140         vis[pos] = true;
141         dfs2(pos, 0);
142         int ans = bridge - maxdeep;
143         printf("%d\n", ans);
144     }
145     return 0;
146 }
View Code

 

转载于:https://www.cnblogs.com/Jiaaaaaaaqi/p/9148334.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值