D - 文理分科 HYSBZ - 3894(最小割)

题目链接:https://cn.vjudge.net/contest/281959#problem/D

题目大意:中文题目

具体思路:

首先说一下最小割:在最小代价的前提下,删除一些边之后,能够使得整个图不再联通。对于这个题,为什么要使用最小割?我的理解就是,建边的时候是按照st->文科->理科->ed.然后,每个人都只能选择一门,所以整个图肯定不连通,然后原来整个图的权值是输入的所有的值,为了使整个图不再联通,我们就需要花费最小的代价使得整个图不在联通,所以这个时候就需要用到最小割了。然后再说一下我之前一直不太理解的一个地方,为什么是所有的文科点连去都连向(都选文科的点),按照正常的方法不应该是拆点的形式才能满足都选文科? 我现在的理解就是,如果有一个点选择了文科,那么就肯定不能选择理科,所以这个满足所有人都选文科的这条路就肯定不能选了。

AC代码:

  1 #include<iostream>
  2 #include<stack>
  3 #include<queue>
  4 #include<iomanip>
  5 #include<stdio.h>
  6 #include<cstring>
  7 #include<cstring>
  8 #include<cmath>
  9 #include<algorithm>
 10 #include<map>
 11 #include<vector>
 12 using namespace std;
 13 # define ll long long
 14 # define maxn 6000000+100
 15 # define inf 0x3f3f3f3f
 16 int prev[maxn];//边的编号
 17 int head[maxn];
 18 int f[2][4]= {{1,-1,0,0},{0,0,1,-1}};
 19 struct node
 20 {
 21     int to;
 22     int flow;
 23     int nex;
 24 } edge[maxn];
 25 int num,st,ed;
 26 void init()
 27 {
 28     memset(head,-1,sizeof(head));
 29     num=0;
 30 }
 31 void addedge(int fr,int to,int flow)
 32 {
 33     edge[num].to=to;
 34     edge[num].flow=flow;
 35     edge[num].nex=head[fr];
 36     head[fr]=num++;
 37     edge[num].to=fr;
 38     edge[num].flow=0;
 39     edge[num].nex=head[to];
 40     head[to]=num++;
 41 }
 42 bool bfs()
 43 {
 44     memset(prev,-1,sizeof(prev));
 45     prev[st]=1;
 46     queue<int>q;
 47     q.push(st);
 48     while(!q.empty())
 49     {
 50         int top=q.front();
 51         q.pop();
 52         for(int i=head[top]; i!=-1; i=edge[i].nex)
 53         {
 54             int temp=edge[i].to;
 55             if(prev[temp]==-1&&edge[i].flow>0)
 56             {
 57                 prev[temp]=prev[top]+1;
 58                 q.push(temp);
 59             }
 60         }
 61     }
 62     return prev[ed]!=-1;
 63 }
 64 int dfs(int u,int flow)
 65 {
 66     if(u==ed)
 67         return flow;
 68     int res=0;
 69     for(int i=head[u]; i!=-1; i=edge[i].nex)
 70     {
 71         int t=edge[i].to;
 72         if(prev[t]==(prev[u]+1)&&edge[i].flow>0)
 73         {
 74             int temp=dfs(t,min(flow,edge[i].flow));
 75             edge[i].flow-=temp;
 76             edge[i^1].flow+=temp;
 77             res+=temp;
 78             flow-=temp;
 79             if(flow==0)
 80                 break;
 81         }
 82     }
 83     if(res==0)
 84         prev[u]=-1;
 85     return res;
 86 }
 87 int n,m;
 88 int dinic()
 89 {
 90     int ans=0;
 91     while(bfs())
 92     {
 93         ans+=dfs(st,inf);
 94     }
 95     return ans;
 96 }
 97 bool judge(int t1,int t2)
 98 {
 99     if(t1>=1&&t1<=n&&t2>=1&&t2<=m)
100         return true;
101     return false;
102 }
103 int main()
104 {
105     init();
106     int sum=0;
107     int tmp;
108     st=1e5,ed=1e5+1;
109     scanf("%d %d",&n,&m);
110     for(int i=1; i<=n; i++)
111     {
112         for(int j=1; j<=m; j++)
113         {
114             scanf("%d",&tmp);
115             sum+=tmp;
116             addedge((i-1)*m+j,ed,tmp);
117         }
118     }
119     for(int i=1; i<=n; i++)
120     {
121         for(int j=1; j<=m; j++)
122         {
123             scanf("%d",&tmp);
124             sum+=tmp;
125             addedge(st,(i-1)*m+j,tmp);
126         }
127     }
128     for(int i=1; i<=n; i++)
129     {
130         for(int j=1; j<=m; j++)
131         {
132             scanf("%d",&tmp);
133             addedge((i-1)*m+j,((i-1)*m+j)+n*m,inf);
134             addedge(((i-1)*m+j)+n*m,ed,tmp);
135             sum+=tmp;
136             for(int k=0; k<4; k++)
137             {
138                 int x=i+f[0][k];
139                 int y=j+f[1][k];
140                 if(judge(x,y))
141                     addedge((x-1)*m+y,((i-1)*m+j)+n*m,inf);
142             }
143         }
144     }
145     for(int i=1; i<=n; i++)
146     {
147         for(int j=1; j<=m; j++)
148         {
149             scanf("%d",&tmp);
150             sum+=tmp;
151             addedge(((i-1)*m+j)+n*m*2,(i-1)*m+j,inf);
152             addedge(st,((i-1)*m+j)+n*m*2,tmp);
153             for(int k=0; k<4; k++)
154             {
155                 int x=i+f[0][k];
156                 int y=j+f[1][k];
157                 if(judge(x,y))
158                     addedge(((i-1)*m+j)+n*m*2,(x-1)*m+y,inf);
159             }
160         }
161     }
162    // cout<<1<<endl;
163     int ans=dinic();
164   //  cout<<1<<endl;
165     printf("%d\n",sum-ans);
166     return 0;
167 }

 

posted @ 2019-02-14 16:12  Let_Life_Stop  阅读(197)  评论(0编辑  收藏  举报