spoj839(Optimal Marks)

省赛比完了,进了工作室学做项目,闲来无聊看看网络流建模,这题想半天没想出硬是想不出和网络流有关系,看了07年胡伯涛的论文才有的思路,觉得这题很经典,所以就写了一下。

  第一次用VS写的题,小小的纪念一下,呵呵。

发现VS的调试功能真强大!

代码:本来定义N是550M是15000的,抱着侥幸的心态加了个0居然AC了,N题目明明是500吗,真是费解!

#include <iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;

#define N 5500
#define M 150000
#define INF 100000000
int U[N],V[N];
bool stable[N],vis[N];
int lable[N],lab[N];
int base;
struct Node{
    int u,v,next;
    int c;
};
struct Graph
{
    Node E[M];
    int first[N];
    int _V,_E,src,dest;
    int que[N],front,rear;
	int d[N];
    void init(int n){
        _V=n,_E=0;
		src=0;dest=_V-1;
        memset(first,-1,4*_V);//!!!
    }
    bool build(int n,int m)
    {
		bool finish=true;
		init(n+2);
		for(int i=0;i<m;i++){
			add(U[i],V[i],1);
			add(V[i],U[i],1);
		}
		for(int i=1;i<=n;i++){
			if(stable[i]){
				if(lable[i])finish=false;
				if(lable[i]&1){
					add(src,i,INF);
					add(i,src,0);
				}
				else add(i,dest,INF),add(dest,i,0);
				lable[i]>>=1;
			}
		}
		return finish;
		/*建图*/
	}
	void DFS(int u){
		vis[u]=true;
		for(int e=first[u];e!=-1;e=E[e].next){
			int c=E[e].c,v=E[e].v;
			if(c&&!vis[v]){
				if(!stable[v])lab[v]|=base;
				DFS(v);
			}
		}
	}		
    void add(int u,int v,int c){
        E[_E].u=u,E[_E].v=v,E[_E].c=c,E[_E].next=first[u],first[u]=_E,_E++;
    }
	bool bfs()
	{
		memset(d,-1,4*_V);//!!!
		d[src]=0;
		front=rear=0;
		que[rear++]=src;
		while(front!=rear){
			int u=que[front++];
			for(int e=first[u];e!=-1;e=E[e].next){
				int v=E[e].v;
				if(d[v]==-1&&E[e].c){
					d[v]=d[u]+1;
					que[rear++]=v;
				}
				if(d[dest]!=-1)return true;
			}
		}
		return false;
	}
	int dfs(int u,int cap)
	{
		if(u==dest)return cap;
		int rest=cap,aug;
		for(int e=first[u];e!=-1&&rest;e=E[e].next){//
			int v=E[e].v,c=E[e].c;
			if(d[v]==d[u]+1&&c){
				aug=dfs(v,rest>c?c:rest);
				rest-=aug;
				E[e].c-=aug;
				E[e^1].c+=aug;
			}
		}
		return cap-rest;
	}
	int dinic(){
		int flow=0;
		while(bfs())flow+=dfs(src,INF);
		return flow;
	}
	void display(){
        for(int i=0; i<_V; i++){
            for(int e=first[i]; e!=-1; e=E[e].next){
                int u=E[e].u,v=E[e].v;
				int c=E[e].c;
                cout<<u<<' '<<v<<' ';
				printf("%d\n",c);
            }
        }
    }
}net;

int main()
{
	#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
	//freopen("out.txt","w",stdout);
    #endif

	int T,n,m;
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&n,&m);
		for(int i=0;i<m;i++){
			scanf("%d%d",U+i,V+i);
		}
		memset(stable,0,sizeof(stable));
		memset(lab,0,sizeof(lab));
		memset(lable,0,sizeof(lable));
		int u,w,k;
		scanf("%d",&k);
		for(int i=0;i<k;i++){
			scanf("%d%d",&u,&w);
			lab[u]=lable[u]=w;
			stable[u]=true;
		}
		base=1;
		while(!net.build(n,m)){	
		//	net.display();
			net.dinic();
			memset(vis,0,sizeof(vis));
			net.DFS(net.src);
			base<<=1;
		}
		for(int i=1;i<=n;i++)printf("%d\n",lab[i]);
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值