POJ 3352 Road Construction 无向图割边 + 缩点
2012-08-23 13:04 javaspring 阅读(180) 评论(0) 编辑 收藏 举报来源:http://poj.org/problem?id=3352
题意:在一个岛上有一些旅游景点,旅游景点之间有路。当施工的时候,若一条路在施工,则这条路是不能走得。问至少还需要增加多少条路,能够保证在施工的时候,任意两个旅游景点之间仍然是可通的。
思路:其实就是一个无向图割边 + 缩点的问题。这样考虑,在一个无向图中,如果一条边是割边,则如果这条边在施工,就会产生不可到达的点。因此可以缩点,缩点后,如果一个点的度为1,说明到达该点的路径只有一条,因此需要增加一条边。也就是说,如果能够保证题目中的条件,则应该在缩点后,任意两个点之间有两条路径可达。所以,若缩点后有n个度为1的点,则应该增加(n+1)/ 2 条边,加1的原因是考虑的奇数个度为1的点。
代码:
#include <iostream> #include <cstdio> #include <algorithm> #include <string.h> #include <vector> using namespace std; #define CLR(arr,val) memset(arr,val,sizeof(arr)) const int N = 1010; vector<int> vv[N]; int low[N],dfn[N],vis[N],instack[N],id[N],degree[N],flag[N][N]; int numpoint,numroad,timeorder,numcnt,numss; void init(){ CLR(low,0); CLR(dfn,0); CLR(vis,0); CLR(id,0); CLR(flag,0); CLR(degree,0); CLR(vv,0); timeorder = 0; numcnt = 0; numss = 0; } int min(int a,int b){ return a < b ? a : b; } void dfs(int x,int fa){ timeorder++; numss++; low[x] = dfn[x] = timeorder; vis[x] = 1; instack[numss] = x; for(int i = 0; i < vv[x].size(); ++i){ int y = vv[x][i]; if(y == fa)continue; if(!dfn[y]){ dfs(y,x); low[x] = min(low[x],low[y]); if(low[y] > dfn[x]){ numcnt++; while(1){ int tt = instack[numss]; id[tt] = numcnt; if(instack[numss--] == y) break; } } } else{ low[x] = min(low[x],dfn[y]); } } } int main(){ //freopen("1.txt","r",stdin); while(scanf("%d%d",&numpoint,&numroad) != EOF){ init(); int x,y; for(int i = 0; i < numroad; ++i){ scanf("%d%d",&x,&y); vv[x].push_back(y); vv[y].push_back(x); } dfs(1,1); int ans = 0; for(int i = 1; i <= numpoint; ++i){ for(int j = 0;j < vv[i].size(); ++j){ int y = vv[i][j]; if(flag[i][y])continue; if(id[i] != id[y]){ flag[i][y] = flag[y][i] = 1; degree[id[i]]++; degree[id[y]]++; } } } for(int i = 1; i <= numcnt; ++i){ if(degree[i] == 1) ans++; } printf("%d\n",(ans+1)/2); } return 0; }