E - tower HYSBZ - 4657 (网络流割点)

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

题目大意:中文题目

具体思路:首先,有矛盾的时候就是两个导弹的运动轨迹会相交的时候,那么我们可以按照这样的思路,在每个导弹不想交的前提下,使得总的消灭数最大。然后我们就可以了按照会相交的方式建图,求出最小割,然后再用总和减去最小割,就能得出最大的消灭量了。

建图的时候,首先横点向竖点连边,权值是inf。每一个炮弹记录他能打到的最大的消灭数,然后对于横着的炮台,从当前的炮台出发到最大的消灭数所在的位置,每一步的权值就是max-当前这个点的权值,最终求的答案的时候,所有炮台的最大值的总和-最小割就是最大消灭数了。

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 const int maxn = 50000+100;
 15 const int inf = 0x3f3f3f3f;
 16 int prev[maxn];
 17 int head[maxn];
 18 int dx[10]= {-1,1,0,0};
 19 int dy[10]= {0,0,-1,1};
 20 int A[600][600],B[600][600],w[600][600];
 21 struct node
 22 {
 23     int to;
 24     int flow;
 25     int nex;
 26 } edge[maxn];
 27 int num,st,ed;
 28 void init()
 29 {
 30     memset(head,-1,sizeof(head));
 31     num=0;
 32 }
 33 void addedge(int fr,int to,int flow)
 34 {
 35     edge[num].to=to;
 36     edge[num].flow=flow;
 37     edge[num].nex=head[fr];
 38     head[fr]=num++;
 39     edge[num].to=fr;
 40     edge[num].flow=0;
 41     edge[num].nex=head[to];
 42     head[to]=num++;
 43 }
 44 bool bfs()
 45 {
 46     memset(prev,-1,sizeof(prev));
 47     prev[st]=1;
 48     queue<int>q;
 49     q.push(st);
 50     while(!q.empty())
 51     {
 52         int top=q.front();
 53         q.pop();
 54         for(int i=head[top]; i!=-1; i=edge[i].nex)
 55         {
 56             int temp=edge[i].to;
 57             if(prev[temp]==-1&&edge[i].flow>0)
 58             {
 59                 prev[temp]=prev[top]+1;
 60                 q.push(temp);
 61             }
 62         }
 63     }
 64     return prev[ed]!=-1;
 65 }
 66 int dfs(int u,int flow)
 67 {
 68     if(u==ed)
 69         return flow;
 70     int res=0;
 71     for(int i=head[u]; i!=-1; i=edge[i].nex)
 72     {
 73         int t=edge[i].to;
 74         if(prev[t]==(prev[u]+1)&&edge[i].flow>0)
 75         {
 76             int temp=dfs(t,min(flow,edge[i].flow));
 77             edge[i].flow-=temp;
 78             edge[i^1].flow+=temp;
 79             res+=temp;
 80             flow-=temp;
 81             if(flow==0)
 82                 break;
 83         }
 84     }
 85     if(res==0)
 86         prev[u]=-1;
 87     return res;
 88 }
 89 int n,m;
 90 int dinic()
 91 {
 92     int ans=0;
 93     while(bfs())
 94     {
 95         ans+=dfs(st,inf);
 96     }
 97     return ans;
 98 }
 99 int cal()
100 {
101     int ans=0,x,y;
102     for (int i = 1; i <= n; i++)
103         for (int j = 1; j <= m; j++)
104         {
105             if (w[i][j] >= 0) continue;
106             int dir = -(w[i][j] + 1),Max = w[i][j] = 0;
107             for (int x = i + dx[dir],y = j + dy[dir]; ;)
108             {
109                 if (x < 1 || x > n || y < 1 || y > m) break;
110                 Max = max(Max,w[x][y]); x += dx[dir]; y += dy[dir];
111             }
112             ans += Max;
113             if (dir <= 1)
114             {
115                 addedge(st,A[i][j],inf);
116                 for (int x = i + dx[dir],y = j + dy[dir]; ;)
117                 {
118                     if (x < 1 || x > n || y < 1 || y > m) break;
119                     addedge(A[x - dx[dir]][y - dy[dir]],A[x][y],Max - w[x - dx[dir]][y - dy[dir]]);
120                     x += dx[dir]; y += dy[dir];
121                 }
122             }
123             else
124             {
125                addedge(B[i][j],ed,inf);
126                 for (int x = i + dx[dir],y = j + dy[dir]; ;)
127                 {
128                     if (x < 1 || x > n || y < 1 || y > m) break;
129                     addedge(B[x][y],B[x - dx[dir]][y - dy[dir]],Max - w[x - dx[dir]][y - dy[dir]]);
130                     x += dx[dir]; y += dy[dir];
131                 }
132             }
133         }
134     return ans;
135 }
136 int main()
137 {
138     init();
139     int tot=0;
140     scanf("%d %d",&n,&m);
141     for(int i=1; i<=n; i++)
142     {
143         for(int j=1; j<=m; j++)
144         {
145             A[i][j]=++tot,B[i][j]=++tot;
146             scanf("%d",&w[i][j]);
147             addedge(A[i][j],B[i][j],inf);
148         }
149     }
150     st=++tot,ed=++tot;
151     int sum=cal();
152     int ans=dinic();
153   //  cout<<sum<<" "<<ans<<endl;
154     printf("%d\n",sum-ans);
155     return 0;
156 }

 

posted @ 2019-02-15 08:48  Let_Life_Stop  阅读(459)  评论(0编辑  收藏  举报