bfs寻找增广路
2015-10-05 17:20
281 查看
选信封
【问题描述】
Dumbulidone和Euphemia玩一个挑卡片游戏.
Dumbulidone会给出N对信封,每个信封里有两张不同颜色的卡片,她会让Euphemia从中挑选任意个信封,但是一对信封中最多只能挑选一个,(信封是透明的,可以看到里面卡片颜色)。等Euphemia挑好后,Dumbulidone会尝试从Euphemia挑出的信封中再选出若干个(不可以不取),把其中的卡片取出,若存在一种方案使得取出的卡片中,每种颜色的卡片都有偶数张,那么Dumbulidone就赢了。Euphemia想知道在自己赢的前提下,她最多能选出多少信封。
【输入格式】
第一行一个整数N。
接下来N行,每行4个整数,描述一对信封中卡片颜色,前两个是一个信封中的,后两个是一个信封中的。
【输出格式】
一个整数,表示答案。
【输入输出样例一】
【输入输出样例二】
【数据范围】
对于30%的数据满足N<=10
对于100%的数据满足N<=300,所有数<=10^7.
最近的训练感觉越来越难。。。苟蒻就是没办法。。。记录下新知识以后说不定用得上吧。。
一开始看到这题想到爆搜,感觉骗个三十分有??但是时间关系没去实践
后来看了题解说是要增广路。。。。唉最不会这个了!!!
花了差不多三天断断续续才大概理解了吧(出题方给我的例程居然是WA0分的。。。)
首先把每张卡片看做一个点,那么每个信封就是一条边,任务是挑最多的边使得没有环生成
对于每对边先各尝试一边能否直接加入,能的话当然最好,如果不能就要尝试对之前的选择进行调整
调整就是找增广路。。大概是找一条未选边->已选边->未选边...->未选边这样的路,然后将沿途所有点取反
称为一次增广
那么如何确定边?
显然,每对给出的边(点)间连一条边,接下来对所有未选边进行一次dfs判断加入后有无环,
有环的话就把环上的每一条边(点)和它连一条边,显然增广的终点是某条加入后不会形成环的边
大概就是这样把。。。
【问题描述】
Dumbulidone和Euphemia玩一个挑卡片游戏.
Dumbulidone会给出N对信封,每个信封里有两张不同颜色的卡片,她会让Euphemia从中挑选任意个信封,但是一对信封中最多只能挑选一个,(信封是透明的,可以看到里面卡片颜色)。等Euphemia挑好后,Dumbulidone会尝试从Euphemia挑出的信封中再选出若干个(不可以不取),把其中的卡片取出,若存在一种方案使得取出的卡片中,每种颜色的卡片都有偶数张,那么Dumbulidone就赢了。Euphemia想知道在自己赢的前提下,她最多能选出多少信封。
【输入格式】
第一行一个整数N。
接下来N行,每行4个整数,描述一对信封中卡片颜色,前两个是一个信封中的,后两个是一个信封中的。
【输出格式】
一个整数,表示答案。
【输入输出样例一】
game.in | game.out |
4 0 1 0 5 5 1 0 5 1 2 0 1 1 5 2 0 | 3 |
【输入输出样例二】
game.in | game.out |
6 1 4 1 4 2 4 2 4 0 3 0 3 0 4 0 4 4 3 4 3 1 3 1 3 | 4 |
【数据范围】
对于30%的数据满足N<=10
对于100%的数据满足N<=300,所有数<=10^7.
最近的训练感觉越来越难。。。苟蒻就是没办法。。。记录下新知识以后说不定用得上吧。。
一开始看到这题想到爆搜,感觉骗个三十分有??但是时间关系没去实践
后来看了题解说是要增广路。。。。唉最不会这个了!!!
花了差不多三天断断续续才大概理解了吧(出题方给我的例程居然是WA0分的。。。)
首先把每张卡片看做一个点,那么每个信封就是一条边,任务是挑最多的边使得没有环生成
对于每对边先各尝试一边能否直接加入,能的话当然最好,如果不能就要尝试对之前的选择进行调整
调整就是找增广路。。大概是找一条未选边->已选边->未选边...->未选边这样的路,然后将沿途所有点取反
称为一次增广
那么如何确定边?
显然,每对给出的边(点)间连一条边,接下来对所有未选边进行一次dfs判断加入后有无环,
有环的话就把环上的每一条边(点)和它连一条边,显然增广的终点是某条加入后不会形成环的边
大概就是这样把。。。
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<string> #include<queue> #include<stack> #include<vector> #include<cstdlib> #include<map> #include<cmath> using namespace std; const int maxn = 600; struct E{ int u,v,use; E () {use = 0;} }edgs[2*maxn]; struct EP{ int v,p; }; int n,i,j,fa[4*maxn],num[4*maxn],cur = 0,From[2*maxn],visp[4*maxn]; bool ok[2*maxn],vis[2*maxn],r[2*maxn]; vector <EP> vp[4*maxn]; vector <int> ve[2*maxn]; queue <int> q; int father (int k) { return k == fa[k]?k:fa[k] = father(fa[k]); } bool Insert (int x) { int fu = father(edgs[x].u); int fv = father(edgs[x].v); if (fu == fv) return false; fa[fu] = fv; edgs[x].use = 1; return true; } bool dfs (int now,int to,int sy) { if (now == to) return true; visp[now] = sy; for (int l = 0; l < vp[now].size(); l++) { int To = vp[now][l].v; if (visp[To] == sy) continue; int Num = vp[now][l].p; r[Num] = true; if (dfs(To,to,sy)) return true; r[Num] = false; } return false; } void Build (int x) { int l; memset(ok,false,sizeof(ok)); memset(r,-1,sizeof(r)); memset(visp,-1,sizeof(visp)); for (l = 0; l <= x; l++) ve[l].push_back(l^1); for (l = 0; l <= x; l++) if (!edgs[l].use) { ok[l] = true; memset(r,false,sizeof(r)); if (!dfs(edgs[l].u,edgs[l].v,l)) continue; ok[l] = false; for (j = 0; j < x; j++) if (r[j]) ve[l].push_back(j); } } bool bfs (int x) { memset(vis,false,sizeof(vis)); memset(From,-1,sizeof(From)); int end = -1; q.push(x); vis[x] = true; while (!q.empty()) { int k = q.front(); q.pop(); for (int l = 0; l < ve[k].size(); l++) { int To = ve[k][l]; if (vis[To]) continue; vis[To] = true; if ((edgs[To].use ^ edgs[k].use)) { From[To] = k; if (ok[To]) { end = To; while (!q.empty()) q.pop(); break; } q.push(To); } } } if (end == -1) return false; for (; end != -1; end = From[end]) edgs[end].use ^= 1; return true; } void Clear() { for (j = 0; j <= cur; j++) fa[j] = j; for (j = 0; j < 4*n; j++) vp[j].clear(); for (j = 0; j < 2*n; j++) ve[j].clear(); for (j = 0; j < 2*i; j++) if (edgs[j].use) { fa[father(edgs[j].u)] = father(edgs[j].v); vp[edgs[j].u].push_back((EP){edgs[j].v,j}); vp[edgs[j].v].push_back((EP){edgs[j].u,j}); } } int main() { #ifndef ONLINE_JUDGE #ifndef YZY freopen("game.in","r",stdin); freopen("game.out","w",stdout); #else freopen("yzy.txt","r",stdin); #endif #endif cin >> n; j = -1; for (i = 0; i < 2*n; i++) { scanf("%d%d",&edgs[i].u,&edgs[i].v); num[++j] = edgs[i].u; num[++j] = edgs[i].v; } sort (num,num + j + 1); for (i = 1; i <= j; i++) if (num[i] != num[i-1]) num[++cur] = num[i]; for (i = 0; i < 2*n; i++) { edgs[i].u = lower_bound(num,num + cur + 1,edgs[i].u) - num; edgs[i].v = lower_bound(num,num + cur + 1,edgs[i].v) - num; } for (i = 0; i < n; i++) { Clear(); if (Insert(2*i)) continue; if (Insert(2*i+1)) continue; Build(2*i+1); if (bfs(2*i)) continue; bfs(2*i+1); } int ans = 0; for (i = 0; i < 2*n; i++) if (edgs[i].use) ++ans; cout << ans; return 0; }
相关文章推荐
- 【HTTP】TCP连接性能初探
- 常见排序算法总结
- JAXB实现JAVA BEAN与XML之间的转换
- 差模辐射干扰&共模辐射干扰
- 第六周 项目1-建立顺序栈算法库
- 第五周——放假中
- 并查集+二分 hnu13433 Dragons
- Java如何连接SQLserver 2008数据库
- list排序
- 第4周 项目5 - 猴子选大王
- 数据结构【线性表(二)链表】项目之循环双链表应用
- iOS开发UI篇—程序启动原理和UIApplication
- 第六周上机实践—项目2—建立链栈算法库
- 第四周项目三 单链表应用(1)
- 四校联训Round3心得体会
- JavaScript 函数参数传递到底是值传递还是引用传递
- Top 30 Nmap Command Examples For Sys/Network Admins
- 第四周项目6-多项式求和
- 第四周项目6-多项式求和
- C#--this关键字