Seikimatsu Occult Tonneru(网络流,状态数(建不建边)不多时,可考虑直接进行枚举

http://acm.hdu.edu.cn/showproblem.php?pid=4309

总结:边可存东西时,可新建一个点x连接u、v,x再连向汇点;

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
#define pb push_back
const ll INF=1e18;
const int inf=0x3f3f3f3f;
const int M=1e5+5;
const int N=1e5+5;

int a[M],head[M],cur[M],deep[M],s,t,tot,firnum,secnum,thnum;
struct node{
    int v,w,nextt;
}e[N];
struct Node{
    int u,v,w,cost;
}fir[M],sec[M],th[M];
void addedge(int u,int v,int w){
    e[tot].v=v;
    e[tot].w=w;
    e[tot].nextt=head[u];
    head[u]=tot++;
    e[tot].v=u;
    e[tot].w=0;
    e[tot].nextt=head[v];
    head[v]=tot++;

}
bool bfs(){
    for(int i=0;i<=t;i++)
        deep[i]=0;
    queue<int>que;
    que.push(s);
    deep[s]=1;
    while(!que.empty()){
        int u=que.front();
        que.pop();
        for(int i=head[u];~i;i=e[i].nextt){
            int v=e[i].v;
            if(e[i].w>0&&deep[v]==0){
                deep[v]=deep[u]+1;
                if(v==t)
                    return true;
                que.push(v);
            }
        }
    }
    return deep[t]==0?false:true;
}
int dfs(int u,int fl){
    if(u==t)
        return fl;
    int x,res=0;
    for(int i=cur[u];~i;i=e[i].nextt){
        int v=e[i].v;
        if(e[i].w>0&&deep[v]==deep[u]+1){
            x=dfs(v,min(fl-res,e[i].w));
            res+=x;
            e[i].w-=x;
            e[i^1].w+=x;
            if(e[i].w)
                cur[u]=1;
            if(res==fl)
                return fl;
        }
    }
    if(res==0)
        deep[u]=0;
    return res;
}
int dinic(){
    int res=0;
    while(bfs()){
        for(int i=0;i<=t;i++)
            cur[i]=head[i];
        res+=dfs(s,inf);
    }
    return res;
}
int n,ans,ansmin,mincost;
void init(){
    memset(head,-1,sizeof(head));
    tot=0;
    mincost=0;
}
void solve(int now){
    init();
    for(int i=1;i<=n;i++)
        addedge(s,i,a[i]);
    for(int i=0;i<firnum;i++){
        addedge(fir[i].u,n+1+i,inf);
        addedge(n+1+i,fir[i].v,inf);
        addedge(n+1+i,t,fir[i].w);
    }
    for(int i=0;i<secnum;i++){
        addedge(sec[i].u,sec[i].v,inf);
    }
    for(int i=0;i<thnum;i++){
        if(now & (1<<i) ){
            addedge(th[i].u,th[i].v,inf);
            mincost+=th[i].cost;
        }
        else
            addedge(th[i].u,th[i].v,1);
    }
    int nowans=dinic();
    if(nowans > ans){
        ans = nowans;
        ansmin = mincost;
    }else if(nowans == ans){
        ansmin=min(ansmin,mincost);
    }
}
int main(){
    int m;
    while(scanf("%d%d",&n,&m)!=EOF){
        ans=0;
        ansmin=inf;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        firnum=secnum=thnum=0;
        s=0;
        t=n+1;
        for(int u,v,w,p,i=1;i<=m;i++){
            scanf("%d%d%d%d",&u,&v,&w,&p);
            if(p<0){
                fir[firnum].u=u;
                fir[firnum].v=v;
                fir[firnum].w=w;
                firnum++;
                t++;
                //addedge(v,t,inf,0);

            }
            else if(p==0){
                sec[secnum].u=u;
                sec[secnum].v=v;
                secnum++;
            }
            else{
                th[thnum].u=u;
                th[thnum].v=v;
                th[thnum].cost=w;
                thnum++;
            }
        }
        //cout<<firnum<<":"<<secnum<<":"<<thnum<<endl;
        for(int i=0;i<=(1<<thnum)-1;i++)
            solve(i);

        if(ans==0)
            puts("Poor Heaven Empire");
        else
            printf("%d %d\n",ans,ansmin);
        //puts("");
    }
    return 0;
}
View Code

 

posted @ 2019-10-14 19:48  starve_to_death  阅读(142)  评论(0编辑  收藏  举报