JZOJ.5331【NOIP2017模拟8.23】壕游戏

Description

 

Input

Output

 

Sample Input

6 8 2 2
4 5 
1 2 4 0 2
1 3 5 0 2
3 4 1 5 1
2 5 1 0 1
4 6 4 2 2
5 6 0 4 2
1 5 5 9 2
2 6 4 5 2

Sample Output

16
 

Data Constraint

 

Hint

类似于一种可撤销的贪心,不难想到这是费用流的模型。

考虑到我们实际会用到的边比实际的边少很多,我们可以动态建边,以减少空间的使用,即当流过了一条边之后再建立第二次流过需要的边(如果有第二次的话)。

然后建立超级源点和超级汇点,跑个费用流就可以了..

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #define M 4000105
 6 #define N 1005
 7 using namespace std;
 8 bool visit[N];
 9 int head[N],pre[N],num,n,m,k,s,dis[N],team[M*2],l,r,ans;
10 struct data{
11     int next,to,flow,power,st,a,c,er;
12 }line[M];
13 void add(int u,int v,int x,int y,int z,int w){
14     num++;
15     line[num].st=u;
16     line[num].to=v;
17     line[num].next=head[u];
18     line[num].flow=w;
19     line[num].power=x+y;
20     line[num].a=x;
21     line[num].c=z;
22     line[num].er=num+1;
23     head[u]=num;
24     num++;
25     line[num].st=v;
26     line[num].to=u;
27     line[num].next=head[v];
28     line[num].flow=0;
29     line[num].power=-x-y;
30     line[num].a=x;
31     line[num].c=z;
32     line[num].er=num-1;
33     head[v]=num;
34 }
35 void SPFA(){
36     int u=0;
37     l=0,r=1;
38     team[1]=0;
39     visit[0]=true;
40     dis[0]=0;
41     while (l<r){
42         u=team[++l];
43         for (int v=0,i=head[u];i;i=line[i].next){
44             v=line[i].to;
45             if ((dis[v]>dis[u]+line[i].power)&&(line[i].flow)){
46                 dis[v]=dis[u]+line[i].power;
47                 pre[v]=i;
48                 if (visit[v]==false){
49                 team[++r]=v;
50                 visit[v]=true;
51                 }
52             }
53             visit[u]=false;
54         }    
55     }
56     if (pre[n+1]==-1) ans=-1;
57 }
58 void solve(){
59     ans+=dis[n+1];
60     int i=pre[line[pre[n+1]].st];
61     do{
62         line[i].flow--;
63         line[line[i].er].flow++;
64         line[i].c--;
65         if (line[i].c>0) 
66             add(line[i].st,line[i].to,line[i].a,line[i].power,line[i].c,1);
67         line[i].c=0;
68         line[line[i].er].c=0;
69         i=pre[line[i].st];
70         }while (line[i].to!=1);
71 }
72 int main(){
73     freopen("game.in","r",stdin);
74     freopen("game.out","w",stdout);
75     scanf("%d%d%d%d",&n,&m,&k,&s);
76     num=0;
77     add(0,1,0,0,99999999,99999999);
78     for (int u,i=1;i<=s;++i){
79         scanf("%d",&u);
80         add(u,n+1,0,0,99999999,99999999);
81     }
82     for (int i=1,u,v,x,y,z;i<=m;i++){
83         scanf("%d%d%d%d%d",&u,&v,&x,&y,&z);
84         add(u,v,x,y,z,1);
85     }
86     ans=0;
87     while (k--){
88         for (int i=0;i<=n+1;++i)
89             dis[i]=99999999,visit[i]=false;
90         pre[n+1]=-1;
91         SPFA();
92         if (ans==-1) break;
93         solve();
94     }
95     printf("%d\n",ans);
96     return 0;
97 }
神奇的代码

改了一个晚上终于发现原来一条边流完后建立另一条边时原来边的C值(可流过次数)要清零QAQ)

当时考试的时候看出来是网络流不想写随便写了个SPFA水了水...

 

posted @ 2017-08-23 22:29  ~Lanly~  阅读(192)  评论(0编辑  收藏  举报