UVA12264 二分最大流,注意pdf的样例是错的
2016-10-02 15:47
423 查看
这里有篇优秀的题解
=====坑点=====
注意input的输入格式,给的pdf里面有两组数据,样例输出只有一组,mdzz
样例是循环读入,mdzz,input里面写的是第一行给数据组数
狗屁不通(制杖+00)
=====vc=====
给n个点的无权无向图(n<=100),每个点有一个非负数ai。若ai==0则此点归敌方所有,若ai>0则此点归你且上面有ai个属于你的士兵。保证至少有一个属于你的点与敌方的点相邻。你可以让你的每个士兵最多移动一次,每次可以待在原地或者去到相邻的属于你的领地,但每个点至少要留1各士兵,使得最薄弱的关口尽量坚固。关口是指与敌方点相邻的点,薄弱与坚固分别指兵少与兵多。
思路:把每个点拆成两个点,一个入度,一个出度,入度向自己的和每个相邻的点的出度连一条边,容量是ai,每个点出度连一条边到汇点,容量为1,那些与敌人相邻的点再多连一条边到汇点,容量是二分的值,我们只需要二分这个值,跑一下网络流,如果满流,表示可以,否则不行。
本篇通过第二个样例讲解思路,下图是第二个样例的建图结果。
敌方的点不需要参与建图,因此图中没有6,7号点。
INF指无穷,mid指二分的中值。
Q:为何需要拆点?
A:我们希望通过拆点来实现每个士兵最多移动一次。下图中每个INF的边都是士兵移动的边,观察后可以发现如此建图士兵只能从入点移动到另一个点的出点,因此最多只能移动一次。(根据题意每次最远移动到相邻的点)
Q:为何出点需要连一条容量为1的边到汇点?
A:为了保证己方的点至少有1个士兵,观察下图 1出 与 2出 满流时说明1和2点至少1个人。
Q:为何要二分?
A:我们要让最薄弱的关口尽量坚固,就得使关口的士兵分配得尽量均匀,然而最大流的算法不能保证分配均匀,我们只好一个个的试,满载就放宽条件,不满载就严加条件,直到试出可行的最大解。
=======
有的版本是i->j+n,
有的版本是i+n->j,
还是没理解透里面的玄机,试了一下两种都过了
=====坑点=====
注意input的输入格式,给的pdf里面有两组数据,样例输出只有一组,mdzz
样例是循环读入,mdzz,input里面写的是第一行给数据组数
狗屁不通(制杖+00)
=====vc=====
给n个点的无权无向图(n<=100),每个点有一个非负数ai。若ai==0则此点归敌方所有,若ai>0则此点归你且上面有ai个属于你的士兵。保证至少有一个属于你的点与敌方的点相邻。你可以让你的每个士兵最多移动一次,每次可以待在原地或者去到相邻的属于你的领地,但每个点至少要留1各士兵,使得最薄弱的关口尽量坚固。关口是指与敌方点相邻的点,薄弱与坚固分别指兵少与兵多。
思路:把每个点拆成两个点,一个入度,一个出度,入度向自己的和每个相邻的点的出度连一条边,容量是ai,每个点出度连一条边到汇点,容量为1,那些与敌人相邻的点再多连一条边到汇点,容量是二分的值,我们只需要二分这个值,跑一下网络流,如果满流,表示可以,否则不行。
本篇通过第二个样例讲解思路,下图是第二个样例的建图结果。
敌方的点不需要参与建图,因此图中没有6,7号点。
INF指无穷,mid指二分的中值。
Q:为何需要拆点?
A:我们希望通过拆点来实现每个士兵最多移动一次。下图中每个INF的边都是士兵移动的边,观察后可以发现如此建图士兵只能从入点移动到另一个点的出点,因此最多只能移动一次。(根据题意每次最远移动到相邻的点)
Q:为何出点需要连一条容量为1的边到汇点?
A:为了保证己方的点至少有1个士兵,观察下图 1出 与 2出 满流时说明1和2点至少1个人。
Q:为何要二分?
A:我们要让最薄弱的关口尽量坚固,就得使关口的士兵分配得尽量均匀,然而最大流的算法不能保证分配均匀,我们只好一个个的试,满载就放宽条件,不满载就严加条件,直到试出可行的最大解。
=======
有的版本是i->j+n,
有的版本是i+n->j,
还是没理解透里面的玄机,试了一下两种都过了
#include<queue> #include<cstdio> #include<vector> #include<string> #include<cstring> #include<iostream> using namespace std; typedef long long LL; const int INF=0x3f3f3f3f; const int N = 10007 ; int n,m,army ; bool mat[107][107]; struct Dinic{ struct Edge{ int from,to,cap,flow; Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){} }; int s,t; vector <Edge> edges; vector < int> G ; //gragh inline void AddEdge(int from,int to,int cap){ edges.push_back(Edge(from,to,cap,0)); edges.push_back(Edge(to,from, 0 ,0)); int top = edges.size(); G[from].push_back(top-2); G[ to ].push_back(top-1); } bool vis ; //use when bfs int d ,cur ;//dist,now edge,use in dfs bool BFS(){ memset(vis,0,sizeof(vis)); queue <int> Q; Q.push(s);d[s]=0;vis[s]=1; while (!Q.empty()){ int x=Q.front();Q.pop(); for (int i=0;i<G[x].size();i++){ Edge &e=edges[G[x][i]]; if (vis[e.to]||e.cap<=e.flow)continue; vis[e.to]=1; d[e.to]=d[x]+1; Q.push(e.to); } } return vis[t]; } int DFS(int x,int a){ if (x==t||a==0) return a; int flow = 0, f; for (int& i=cur[x];i<G[x].size();i++){ Edge& e=edges[G[x][i]]; if (d[x]+1!=d[e.to])continue; if ((f=DFS(e.to,min(a,e.cap-e.flow)))<=0)continue; e.flow += f; edges[G[x][i]^1].flow-=f;//反向边 flow+=f; a-=f; if (a==0) break; } return flow; } int maxFlow(int s,int t){ this->s=s;this->t=t; int flow=0; while(BFS()){ memset(cur,0,sizeof(cur)); flow += DFS(s,INF) ; } return flow; } bool check(int mid){ s = 0, t = (n<<1)+2; edges.clear(); for (int i=0;i<=n*2+2;i++)G[i].clear(); int sum = 0; for (int i=1;i<=n;i++)if (army[i]){ bool boder = 0; AddEdge(s, i ,army[i]); AddEdge(i,n+i,army[i]); for (int j=1;j<=n;j++)if (mat[i][j]){ if (army[j])AddEdge(i,j+n,INF); else boder = 1; } if(boder){sum+=mid;AddEdge(i+n,t,mid);} else { sum ++; AddEdge(i+n,t, 1 ); } } return sum==maxFlow(s,t); } }g; int main(){ //freopen("in.txt","r",stdin); int T;scanf("%d",&T); for (char ch;T--;){ scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&army[i]); getchar(); for (int i=1;i<=n;getchar(),i++){ for (int j=1;j<=n;j++){ scanf("%c",&ch); mat[i][j]=(ch=='Y'); } } int L=0,R=N-1,ans; for (;L<R;){ int mid = (L +R) >> 1 ; if (g.check(mid)){ ans = mid ; L = mid + 1; }else R = mid; } printf("%d\n",ans); } return 0; }
相关文章推荐
- uva 12264 (Risk) 二分 + 最大流
- UVA 12264 二分+最大流 基础题
- Risk UVA - 12264 拆点法+最大流+二分 最少流量的节点流量尽量多。
- UVA 12264 Risk 二分最大流
- UVa live3415Guardian of Decency(二分最大匹配之最大独立点集)
- UVa670 - The dog task(最大二分匹配)
- uva 10122 Mysterious Mountain && ZOJ 1231 Mysterious Mountain (二分+二部图最大匹配)
- uva 10122 Mysterious Mountain && ZOJ 1231 Mysterious Mountain (二分+二部图最大匹配)
- UVA 11419 SAM I AM(最大二分匹配&最小点覆盖:König定理)
- UVA - 12264 Risk (二分,网络流)
- UVa live6525Attacking rooks(二分最大匹配之最大匹配)
- UVA 714 Copying Books 最大值最小化问题 (贪心 + 二分)
- [最大流法二分匹配]uva753
- UVA-1345 - Jamie's Contact Groups(最大流+二分)
- uva 1345 Jamie's Contact Groups (最大流+二分)
- uva 714 - Copying Books(贪心 最大值最小化 二分)
- Uva 714 最大值最小化 (贪心+二分)
- UVA 714 Copying Books 最大值最小化问题 (贪心 + 二分)
- uva 10122 Mysterious Mountain and ZOJ 1231 Mysterious Mountain (二分+二部图最大匹配)
- uva--714+二分(最大值最小化问题)