[HDU4309] Seikimatsu Occult Tonneru

咋一看 这不网络扩容(UVA11245)吗 然后自信写一样的代码 结果WA一半 

好吧 那个只能扩一条 这个可以扩很多条所以要枚举子集 感觉用位向量法比较方便的样子..

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
const int MAXN = 200;
const int MAXM = 5000;
const int INF = 0x3f3f3f3f;
using namespace std;
int n, m, S, T, k, ST1, ST2, CAP, A[MAXN+10], M, List[13];
int Max, Ans, Pos[15];
bool fix[15];
struct node{
	int u, v, p, w;
}Edge[MAXM+10];
template <int maxn, int maxm>
struct Isap
{
    int ecnt;
    int d[maxn+10], pre[maxn+10], cur[maxn+10], gap[maxn+10];
    int adj[maxn+10];
    struct node {
        int v, next, c, f;
    }Edge[maxm*2+10];
    void init() { memset(adj, -1, sizeof(adj)); ecnt = 0; }
    void addedge(int u, int v, int c)
    {
        Edge[ecnt].v = v;
        Edge[ecnt].c = c;
        Edge[ecnt].f = 0;
        Edge[ecnt].next = adj[u];
        adj[u] = ecnt++;
    }
    void add(int u, int v, int c)
    {
        addedge(u, v, c);
        addedge(v, u, 0);
    }
    void init_dis(int t)
    {
        queue <int> q;
        memset(d, -1, sizeof(d));
        memset(gap, 0, sizeof(gap));
        d[t] = 0;
        q.push(t);
        while(!q.empty())
        {
            int u = q.front(); q.pop();
            gap[d[u]]++;
            for(int i = adj[u]; ~i; i = Edge[i].next) 
            {
                int v = Edge[i].v;
                if(d[v] == -1) { d[v] = d[u] + 1; q.push(v); }
            }
        }
    }
    int ISAP(int s, int t, int num)
    {
        init_dis(t);
        int ans = 0, u = s;
        int Flow = INF;
        memcpy(cur, adj, sizeof(adj));
        while(d[s] < num)
        {
            int &i = cur[u];
            for(; ~i; i = Edge[i].next)
            {
                int v = Edge[i].v;
                if(Edge[i].c > Edge[i].f && d[u] == d[v] + 1)
                {
                    u = v;
                    pre[v] = i;
                    Flow = min(Flow, Edge[i].c - Edge[i].f);
                    if(u == t)
                    { 
                        while(u != s) {
                            int j = pre[u];
                            Edge[j].f += Flow;
                            Edge[j^1].f -= Flow;
                            u = Edge[j^1].v;
                        }
                        ans += Flow;
                        Flow = INF;
                    }
                    break;
                }
            }
            if(i == -1)
            {
                if(--gap[d[u]] == 0) break;
                int dmin = num - 1;
                cur[u] = adj[u];
                for(int j = adj[u]; ~j; j = Edge[j].next) if(Edge[j].c > Edge[j].f) dmin = min(dmin, d[Edge[j].v]);
                d[u] = dmin+1;
                gap[d[u]]++;
                if(u != s) u = Edge[pre[u]^1].v;
            }
        }
        return ans;
    }
};  
Isap <MAXN+10, MAXM+10> sap, tmp;
void Solve(int cur)
{
	int sum = 0, Flow;
	if(cur == M)
	{
		memcpy(sap.Edge, tmp.Edge, sizeof(sap.Edge));
		for(int i = 0; i < M; i++) 
			if(fix[i])
			{
				sum += A[i];
				sap.Edge[Pos[i]].c = INF;
			}
		Flow = sap.ISAP(S, T, n+2);
		if(Flow > Max) {
			Max = Flow; Ans = sum; return ;
		}
		if(Flow == Max && sum < Ans) { Ans = sum; return ; }
		return ;
	}
	fix[cur] = true;
	Solve(cur+1);
	fix[cur] = false;
	Solve(cur+1);
}
int main()
{
	while(scanf("%d%d", &n, &m) == 2 && n)
	{
		sap.init();
		M = Ans = Max = 0;
		S = n + 1, T = n + 2;
		for(int i = 1; i <= n; i++) {
			int x; scanf("%d", &x);
			sap.add(S, i, x);
		}
		for(int i = 0; i < m; i++)
			scanf("%d%d%d%d", &Edge[i].u, &Edge[i].v, &Edge[i].w, &Edge[i].p);
		for(int i = 0; i < m; i++)
		{
			int u = Edge[i].u, v = Edge[i].v, w = Edge[i].w, p = Edge[i].p;
			if(p < 0) {
				sap.add(u, v, INF);
				sap.add(u, T, w);
			}
			else if(p == 0) sap.add(u, v, INF);
			else {
				Pos[M] = sap.ecnt; A[M++] = w;
				sap.add(u, v, 1);
			}
		}
		memcpy(tmp.Edge, sap.Edge, sizeof(sap.Edge));
		Solve(0);
		if(Max) printf("%d %d\n", Max, Ans);
		else printf("Poor Heaven Empire\n");
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值