Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

带需求的可行流问题 可以转化为最大流

Posted by cycpp at 2009-09-08 18:54:31 on Problem 1637
//但是老RE没法了!
#include <iostream>
using  namespace  std;   
const  int MAXN = 205;//点的标号[0..MAXN-1]
const  int MAXM2 = 5005*2;
const  int INF  = (1<<20);
struct  Edge   
{   
    int  st, ed;
    int  next; 
    int  flow;//边的剩余容量 
}edge[MAXM2];//残留网络
//head 链接表的头结点
int head[MAXN];
int   E, src, dest; 
void  Init(int s, int t)//先初始化,后读入图
{   
    E = 0;   
    src = s;   
    dest = t;
    memset(head, -1, sizeof(head));   
}
void  add_edge(int  u, int v, int w)//u-->v:w
{   //允许任意形状的网络
    edge[E].st = u; edge[E].ed = v;   
    edge[E].flow = w; edge[E].next = head[u];   
    head[u] = E++;   

    edge[E].st = v; edge[E].ed = u;   
    edge[E].flow = 0; edge[E].next = head[v];   
    head[v] = E++;   
}
//////////////////////dinic
int d[MAXN],que[MAXN],stk[MAXN],edgptr[MAXN];
bool  dinic_bfs()   
{   
    int  i, j ,rear=1;
    memset(d, -1, sizeof(d)); 
    que[0] = src; d[src] = 0;   
    for(i = 0; i < rear; i++)   
        for(j = head[que[i]]; j != -1; j = edge[j].next)   
            if(d[edge[j].ed] == -1 && edge[j].flow > 0)   
            {   
                d[edge[j].ed] = d[que[i]]+1;   
                que[rear++] = edge[j].ed;  
            }   
	return  d[dest] >= 0;
}
int  dinic_dfs()
{   
    int  ans = 0, top =0 ,cur, ptr, minf, i,pose;
    stk[top++] = src; 
    while(top) 
    {   
		for(cur=stk[top-1],i = head[cur]; i != -1; i = edge[i].next)   
		{   
			if(d[edge[i].ed] == d[cur]+1 && edge[i].flow > 0 )   
			{   
				stk[top++] = edge[i].ed;
				cur=edge[i].ed;
				edgptr[cur] = i;
				break;   
			}   
		}   
		if(i == -1)
		{   
			d[cur] = 0;   //删点
			--top;
			continue;
		} 
        //update the flow 
        if(cur == dest)
        {   
            minf = INF;
            while(cur != src) //必须到达后才开始找minf 
            {   
                ptr = edgptr[cur];
                if(edge[ptr].flow < minf) minf = edge[ptr].flow;   
                cur = edge[ptr].st;
            }   
            cur = dest; 
            while(cur != src)   
            {   
                ptr = edgptr[cur];   
                edge[ptr].flow -= minf;   
                edge[ptr^1].flow += minf;   
                if(edge[ptr].flow == 0) pose = edge[ptr].st;
                cur = edge[ptr].st; 
            }   
            while(top > 0 && stk[top-1] != pose) top--; 
            ans += minf;
        }   
    }   
    return  ans;   
}   
int  Dinic()   
{   
    int  ans = 0, t;   
    while(dinic_bfs()) 
    {   
        t = dinic_dfs();
        if(t) ans += t;   
        else  break;   
    }   
    return  ans;   
}
////////////////////////////////////////////////高效ac了n多题
//dicnic后dfs(s)即可求的最小割集
int need[MAXN];
int deg[MAXN];
int main()
{
	int t,n,m,s,f;
	cin>>t;
	while(t--)
	{
		memset(need,0,sizeof(need));
		memset(deg,0,sizeof(deg));
		cin>>n>>m;
		Init(0,n+1);
		while(m--)
		{
			cin>>s>>t>>f;
			deg[s]++;deg[t]++;
			if(s==t)continue;
			if(f==1)
			{
				need[s]--;
				need[t]++;
			}
			else
			{
				add_edge(s,t,1);
				add_edge(t,s,1);
			}
		}
		for(f=1;f<=n;++f)if(deg[f]%2==1)break;
		if(f<=n)
		{
			cout<<"impossible\n";
			continue;
		}
		int needsum=0;
		for(f=1;f<=n;++f)
		{
			if(need[f]<0)add_edge(f,dest,-need[f]);
			if(need[f]>0){add_edge(src,f,need[f]);needsum+=need[f];}
		}
		int ans=Dinic();
		if(ans==needsum)cout<<"possible\n";
		else cout<<"impossible\n";
	}

	return 0;
}

Followed by:

Post your reply here:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator