【POJ - 3177】Redundant Paths(边双连通分量,去重边)
題干:
In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numbered 1..F) to another field, Bessie and the rest of the herd are forced to cross near the Tree of Rotten Apples. The cows are now tired of often being forced to take a particular path and want to build some new paths so that they will always have a choice of at least two separate routes between any pair of fields. They currently have at least one route between each pair of fields and want to have at least two. Of course, they can only travel on Official Paths when they move from one field to another.?
Given a description of the current set of R (F-1 <= R <= 10,000) paths that each connect exactly two different fields, determine the minimum number of new paths (each of which connects exactly two fields) that must be built so that there are at least two separate routes between any pair of fields. Routes are considered separate if they use none of the same paths, even if they visit the same intermediate field along the way.?
There might already be more than one paths between the same pair of fields, and you may also build a new path that connects the same fields as some other path.
Input
Line 1: Two space-separated integers: F and R?
Lines 2..R+1: Each line contains two space-separated integers which are the fields at the endpoints of some path.
Output
Line 1: A single integer that is the number of new paths that must be built.
Sample Input
7 7 1 2 2 3 3 4 2 5 4 5 5 6 5 7Sample Output
2Hint
Explanation of the sample:?
One visualization of the paths is:?
Building new paths from 1 to 6 and from 4 to 7 satisfies the conditions.?
1 2 3+---+---+ : | |: | |6 +---+---+ 4/ 5 :/ :/ :7 + - - - -Check some of the routes:?
1 – 2: 1 –> 2 and 1 –> 6 –> 5 –> 2?
1 – 4: 1 –> 2 –> 3 –> 4 and 1 –> 6 –> 5 –> 4?
3 – 7: 3 –> 4 –> 7 and 3 –> 2 –> 5 –> 7?
Every pair of fields is, in fact, connected by two routes.?
It's possible that adding some other path will also solve the problem (like one from 6 to 7). Adding two paths, however, is the minimum.
題目大意:
有n個牧場,Bessie 要從一個牧場到另一個牧場,要求至少要有2條獨立的路可以走。現已有m條路,求至少要新建多少條路,使得任何兩個牧場之間至少有兩條獨立的路。兩條獨立的路是指:沒有公共邊的路,但可以經過同一個中間頂點。
解題報告:
在POJ - 3352的基礎上,加個去重邊可以過。
但是對于這組樣例就過不了
2 2 1 2 2 1按照題意答案應該是0,但是AC代碼1的答案輸出是1.
所以再次證明了不能只看low數組是否相同來判斷是否屬于一個邊雙連通分量
AC代碼1:(但是其實是錯誤代碼只不過是數據若)
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define F first #define S second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 2e5 + 5; vector<int> vv[MAX]; int n,m; bool mm[5555][5555]; int dfn[MAX],low[MAX],out[MAX]; int stk[MAX],index,clk,scc; void init() {for(int i = 1; i<=n; i++) {vv[i].clear();dfn[i]=low[i]=out[i]=0;for(int j = 1; j<=n; j++) mm[i][j]=0;}clk = index = scc = 0; } void tarjan(int x,int rt) {dfn[x] = low[x] = ++clk;int up = vv[x].size();for(int i = 0; i<up; i++) {int v = vv[x][i];if(v == rt) continue;if(dfn[v] == 0) {tarjan(v,x);low[x] = min(low[x],low[v]);}else low[x] = min(low[x],dfn[v]);} } int main() {while(~scanf("%d",&n)) {scanf("%d",&m);init();for(int u,v,i = 1; i<=m; i++) {scanf("%d%d",&u,&v);if(mm[u][v]==1) continue;mm[u][v]=mm[v][u]=1;vv[u].pb(v);vv[v].pb(u);}for(int i = 1; i<=n; i++) {if(dfn[i] == 0) tarjan(i,-1);//因為題目保證是連通圖所以其實可以直接tarjan(1,-1)的 }for(int up,u = 1; u<=n; u++) {up = vv[u].size();for(int v,j = 0; j<up; j++) {v = vv[u][j];//圖G中Low值相同的兩個點必定在同一個邊雙連通分量(即同一個縮點)中if(low[u] == low[v]) continue;//檢查i、j是否不在同一個縮點中out[low[u]]++;//out[low[v]]++;//注意是對縮點操作,不是對原圖的點}}int ans = 0;//記錄總度數=1(葉子)的縮點for(int i = 1; i<=n; i++) {if(out[i] == 1) ans++;//由于是無向圖,因此每個縮點的度都重復計算了2次,因此度數==2才是葉子結點}printf("%d\n",(ans+1)/2);//將一棵樹連成一個邊雙連通分量至少需要添加的邊數=(葉子節點數+1)/2}return 0 ; }AC代碼2:(注意對于重邊的處理,這里采用kuangbin的寫法,當然如果你是鄰接表的寫法也可以用下面附的那部分代碼)
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define F first #define S second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 2e5 + 5; vector<int> vv[MAX]; int n,m; int dfn[MAX],low[MAX],out[MAX],col[MAX]; int stk[MAX],index,clk,bcc; void init() {for(int i = 1; i<=n; i++) {vv[i].clear();dfn[i]=low[i]=out[i]=0;}clk = index = bcc = 0; } void tarjan(int x,int rt) {dfn[x] = low[x] = ++clk;stk[++index] = x;int up = vv[x].size(),cntrt=0;for(int i = 0; i<up; i++) {int v = vv[x][i];if(v == rt && cntrt == 0) {cntrt++;continue;}if(dfn[v] == 0) {tarjan(v,x);low[x] = min(low[x],low[v]);}else low[x] = min(low[x],dfn[v]);}if(dfn[x] == low[x]) {bcc++;while(1) {int tmp = stk[index];index--;col[tmp] = bcc;if(tmp == x) break;}} } int main() {while(~scanf("%d",&n)) {scanf("%d",&m);init();for(int u,v,i = 1; i<=m; i++) {scanf("%d%d",&u,&v);vv[u].pb(v);vv[v].pb(u);}for(int i = 1; i<=n; i++) {if(dfn[i] == 0) tarjan(i,-1);//因為題目保證是連通圖所以其實可以直接tarjan(1,-1)的 }for(int up,u = 1; u<=n; u++) {up = vv[u].size();for(int v,j = 0; j<up; j++) {v = vv[u][j];//圖G中Low值相同的兩個點必定在同一個邊雙連通分量(即同一個縮點)中if(col[u] == col[v]) continue;//檢查i、j是否不在同一個縮點中out[col[u]]++;//out[low[v]]++;//注意是對縮點操作,不是對原圖的點}}int ans = 0;//記錄總度數=1(葉子)的縮點for(int i = 1; i<=n; i++) {if(out[i] == 1) ans++;//由于是無向圖,因此每個縮點的度都重復計算了2次,因此度數==2才是葉子結點}printf("%d\n",(ans+1)/2);//將一棵樹連成一個邊雙連通分量至少需要添加的邊數=(葉子節點數+1)/2}return 0 ; }附代碼:?
void tarjan(int x,int rti) {dfn[x] = low[x] = ++clk;stk[++index] = x;for(int i = head[x]; ~i; i=e[i].ne) {int v = e[i].to;if(i == rti^1) continue;if(dfn[v] == 0) {tarjan(v,i);low[x] = min(low[x],low[v]);}else low[x] = min(low[x],dfn[v]);}if(dfn[x] == low[x]) {bcc++;while(1) {int tmp = stk[index];index--;col[tmp] = bcc;if(tmp == x) break;}} }?
總結
以上是生活随笔為你收集整理的【POJ - 3177】Redundant Paths(边双连通分量,去重边)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: slserve.exe - slserv
- 下一篇: 【牛客 - 157B】凤凰(树上并查集,