hdu4888 最大流多解问题 最大流残存网络存在环

题目是最大流问题,只是需要判断最大流的多解,可以通过判断最大流中是否存在环。

#include<vector>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<queue>
using namespace std;
#define INF 1e9
#define maxn 1000
#define rep(i,x,y) for(int i=x;i<=y;i++)
#define mset(x) memset(x,0,sizeof(x))

struct Edge{
	int from, to, cap, flow;
	Edge(int from, int to, int cap, int flow):from(from), to(to), cap(cap), flow(flow){}
};

struct Dicnic{
	int n, m, s, t;
	vector<Edge> edges;
	vector<int> G[maxn];
	bool vis[maxn];
	int d[maxn], cur[maxn];

	void init(int n){
		this->n = n;
		mset(cur);
		mset(d);
		rep(i,0,n)	G[i].clear();
		edges.clear();
	}

	void AddEdge(int from, int to, int cap){
		edges.push_back( Edge(from, to, cap, 0) );
		edges.push_back( Edge(to, from, 0, 0) );
		m=edges.size();
		G[from].push_back(m-2);
		G[to].push_back(m-1);
	}

	bool BFS() {
		mset(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) {
					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] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0 ) {
				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()){
			mset(cur);
			flow += DFS(s,INF);
		}
		return flow;
	}

	bool isloop[maxn];
	bool judge(int u, int fa){//以一个点为起点,判断是否有环
		if(isloop[u])
			return true;
		isloop[u]=1;
		for(int i=0;i<G[u].size();i++)
		{
			if(G[u][i] == (fa^1)) //不能从过来的边回去
				continue;
			if(edges[G[u][i]].to == t || edges[G[u][i]].to == s) //不能跑到源点和起点
				continue;
			if(edges[G[u][i]].cap-edges[G[u][i]].flow > 0)
				if( judge(edges[G[u][i]].to, G[u][i]) )
					return true;
		}
		isloop[u]=0;
		return false;
	}
	bool haveloop(int x){
	//判断整个图是否有环,枚举左边的每个点(行节点)作为起点,
		mset(isloop);
		rep(i,1,x){
			if(judge(i,-1))
				return true;
		}
		return false;
	}

	int mat[410][410];
	void getAns(int x){ //输出唯一解 
		mset(mat);
		for(int i=0;i<edges.size();i++){
			if(edges[i].cap && edges[i].from>0 && edges[i].from<=x){
				mat[edges[i].from][edges[i].to-x] = edges[i].flow;
			}
		}
	}

};

Dicnic solve;
int n, m, k, row[410], col[410];

int main(){
//	freopen("a.txt","r",stdin);
//	freopen(".out","w",stdout);
	while(cin>>n>>m>>k){
		int flag=1,sumR=0,sumC=0;//Impossible是0,unique是1,not unique是2
		
		solve.init(n+m+2);
		rep(i,1,n){
			cin>>row[i];
			solve.AddEdge(0,i,row[i]);
			if(row[i]>m*k)	flag=0;
			sumR += row[i];
		}
		rep(i,1,m){
			cin>>col[i];
			solve.AddEdge(n+i,n+m+1,col[i]);
			if(col[i]>n*k)	flag=0;
			sumC += col[i];
		}
		if(sumR != sumC) flag=0;
		if(flag==0){ puts("Impossible"); continue; }

		rep(i,1,n)
			rep(j,1,m){
				solve.AddEdge(i,n+j,k);
			}
		int res=solve.MaxFlow(0,n+m+1);
		if(res != sumC)//满流
			puts("Impossible");
		else{
			if(solve.haveloop(n))
				puts("Not Unique");
			else{
				puts("Unique");
				solve.getAns(n);
				rep(i,1,n){
					for(int j=1;j<m;j++)
						printf("%d ",solve.mat[i][j]);
					printf("%d\n",solve.mat[i][m]);
				}
			}
		}
	}
	return 0;
}

/*
DESCRIPTION:
n*m的格子,给出每行的元素和,每列的元素和
每个格子的最大值为k
询问是否有解

如果row[i]>m*k || col[i]>n*k 则无解

*/


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值