Thieves----简单最小割

题目:http://acm.hdu.edu.cn/showproblem.php?pid=3491

注:拆点

源代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
#define inf 1e9

using namespace  std;

typedef int typec;
const int N = 220, M = 40000;

int n,m,s,t,u,v,cas,ans;

int a[N];

struct FlowNetwork {
	int e, head[N], d[N], vd[N], pre[N], cur[N];
	int nxt[M], eu[M], ev[M];
	typec c[M];
	void init() { e = 0; memset(head,-1,sizeof(head)); }
	void addedge(int u, int v, typec w) {
		eu[e]=u; ev[e]=v; c[e]=w; nxt[e]=head[u]; head[u]=e++;
		eu[e]=v; ev[e]=u; c[e]=0; nxt[e]=head[v]; head[v]=e++;
	//无向图中第二个c[e]=w;
	}
	typec sap(int s, int t, int n){
		int i, u;
		memset(d,0,sizeof(d)); memset(vd,0,sizeof(vd));
		vd[0] = n;
		cur[u = s] = head[s];
		pre[s] = -1;
		typec temp, ans = 0;
		while (d[s] < n) {
			if(u == t){
				for(temp = inf, i = pre[u]; ~i; i = pre[eu[i]])
					temp = min(temp, c[i]);
				for(i = pre[u]; ~i; i = pre[eu[i]]){
					c[i] -= temp; c[i ^ 1] += temp;
				}
				ans += temp;  u = s;
			}
			for (i = cur[u]; ~i; i = nxt[i])
				//if (c[i] > eps && d[u] == d[ev[i]] + 1){
				if (c[i] > 0 && d[u] == d[ev[i]] + 1){
					cur[u] = i;		//当前弧优化
					pre[u = ev[i]] = i;
					break;
				}
			if(i == -1){
				cur[u] = head[u];
				if (--vd[d[u]] == 0)break;
				vd[++d[u]]++;
				if(u != s)u = eu[pre[u]];
			}
		}
		return ans;
	}
};


int solve()
{
    FlowNetwork tmp;
    tmp.init();
    memset(a,0,sizeof(a));
    for(int i=1;i<=n;i++)
      {
          scanf("%d",&a[i]);
          if(i!=s&&i!=t)
          tmp.addedge(i,i+n,a[i]);
      }
      tmp.addedge(s,s+n,inf);
      tmp.addedge(t,t+n,0);
    for(int i=0;i<m;i++)
    {
        scanf("%d %d",&u,&v);
        tmp.addedge(u+n,v,inf);
        tmp.addedge(v+n,u,inf);
    }
    return tmp.sap(s,t,2*n);
}

int main()
{
    //freopen("D:\\a.txt","r",stdin);
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d %d %d %d",&n,&m,&s,&t);
        ans=solve();
        printf("%d\n",ans);
    }
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值