zoukankan      html  css  js  c++  java
  • D

    题目链接: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
    ",sum-ans);
    166     return 0;
    167 }
  • 相关阅读:
    组合继承
    包装明星——封装
    多种添加公用方法的方式
    专有扩展
    插入标记
    mac 命令操作
    php(apache)切换版本
    SqlServer索引+约束篇章
    sqlserver 常用语法
    C# 通用数据访问类
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10375188.html
Copyright © 2011-2022 走看看