线性规划与网络流24——太空飞行计划问题

来源:互联网 发布:cad网络拓扑图下载 编辑:程序博客网 时间:2024/06/05 18:20

题目链接点这里

最大权闭合子图问题

构图:将正权点与源点相连,边的cap为权值。负权点与汇点相连边的cap为abs(权值)。负权点与正权点的边cap为INF。

有个结论就是,闭合子图的最大权=sum(正权点)-最大流

具体的证明有点迷,我看了好久才看懂的,,可能以后会写一篇博客讲解



#include<iostream>#include<cstdio>#include<math.h>#include<algorithm>#include<map>#include<set>#include<bitset>#include<stack>#include<queue>#include<string.h>#include<cstring>#include<vector>#include<time.h>#include<stdlib.h>using namespace std;#define INF 0x3f3f3f3f#define INFLL 0x3f3f3f3f3f3f3f3f#define FIN freopen("input.txt","r",stdin)#define mem(x,y) memset(x,y,sizeof(x))typedef unsigned long long ULL;typedef long long LL;#define MX 2222#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1typedef pair<pair<int,int>,int> PIII;typedef pair<int,int> PII;int n,m;int head[MX],rear;struct Edge{    int to,nxt,cap;} edge[111*MX];void edge_init(){    mem(head,-1);    rear=0;}void edge_add(int a,int b,int cap){    edge[rear].cap=cap;    edge[rear].nxt=head[a];    edge[rear].to=b;    head[a]=rear++;}bool vis[MX];int d[MX],cur[MX];bool BFS(int s,int t){    mem(vis,0);    queue<int> my;    my.push(s);    vis[s]=1;    d[s]=0;    d[t]=-1;    while(!my.empty())    {        int u=my.front();        my.pop();        for(int i=head[u]; ~i; i=edge[i].nxt)        {            int v=edge[i].to;            if(vis[v]||!edge[i].cap) continue;            d[v]=d[u]+1;            vis[v]=1;            my.push(v);        }    }    return d[t]!=-1;}int DFS(int x,int t,int a){    if(x==t||a==0) return a;    int flow=0,f;    for(int &i=cur[x]; ~i; i=edge[i].nxt)    {        int v=edge[i].to;        if(d[v]==d[x]+1&&(f=DFS(v,t,min(a,edge[i].cap))))        {            edge[i].cap-=f;            edge[i^1].cap+=f;            flow+=f;            a-=f;            if(a==0) break;        }    }    return flow;}int Dinic(int s,int t){    int flow=0;    while(BFS(s,t))    {        memcpy(cur,head,sizeof(head));        flow+=DFS(s,t,INF);    }    return flow;}bool lof;bool Int(int &a){    if(lof) return lof=0;    char c;    for(c=getchar(); c<'0'||c>'9'; c=getchar())if(c=='\n')return 0;    a=c-'0';    for(c=getchar(); c>='0'&&c<='9'; c=getchar())a=a*10+c-'0';    lof=c=='\n';    return 1;}int main(){    FIN;    while(~scanf("%d%d",&n,&m))    {        edge_init();        int sum=0;        for(int i=1; i<=n; i++)        {            int x;            scanf("%d",&x);            sum+=x;            edge_add(0,i,x);            edge_add(i,0,0);            lof=0;            int w;            while(Int(w))            {                edge_add(i,n+w,INF);                edge_add(n+w,i,0);            }        }        for(int i=1; i<=m; i++)        {            int x;            scanf("%d",&x);            edge_add(n+i,n+m+1,x);            edge_add(n+m+1,n+i,0);        }        int ans=sum-Dinic(0,n+m+1);        bool vvis[MX]= {0};        queue<int> q;        q.push(0);        vvis[0]=1;        while(!q.empty())        {            int u=q.front();            q.pop() ;            for(int i=head[u]; ~i; i=edge[i].nxt)            {                int v=edge[i].to;                if(edge[i].cap&&vvis[v]==0)                {                    vvis[v]=1;                    q.push(v);                }            }        }        int cnt1=0,cnt2=0;        for(int i=1; i<=n; i++) if(vvis[i]) cnt1++;        for(int i=n+1; i<=n+m; i++) if(vvis[i]) cnt2++;        for(int i=1; i<=n; i++) if(vvis[i])            {                cnt1--;                printf("%d%c",i,cnt1==0?'\n':' ');            }        for(int i=n+1; i<=n+m; i++) if(vvis[i])            {                cnt2--;                printf("%d%c",i-n,cnt2==0?'\n':' ');            }        printf("%d\n",ans);    }    return 0;}


0 0
原创粉丝点击