[bzoj1877]晨跑

很显然是网络流,对于点的限制,拆点建流量为1的边,之后跑最小费用最大流即可(由此很显然可以发现原图边的流量也只需要1)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 405
 4 struct ji{
 5     int nex,to,len,cost;
 6 }edge[N*N];
 7 queue<int>q;
 8 int E,n,m,x,y,z,ans1,ans2,head[N],d[N],from[N],vis[N];
 9 void add(int x,int y,int z,int w){
10     edge[E].nex=head[x];
11     edge[E].to=y;
12     edge[E].len=z;
13     edge[E].cost=w;
14     head[x]=E++;
15     if (E&1)add(y,x,0,-w);
16 }
17 bool spfa(){
18     memset(d,0x3f,sizeof(d));
19     memset(vis,0,sizeof(vis));
20     q.push(1);
21     d[1]=0;
22     while (!q.empty()){
23         int k=q.front();
24         q.pop();
25         vis[k]=0;
26         for(int i=head[k];i!=-1;i=edge[i].nex){
27             int v=edge[i].to;
28             if ((edge[i].len)&&(d[v]>d[k]+edge[i].cost)){
29                 d[v]=d[k]+edge[i].cost;
30                 from[v]=i;
31                 if (!vis[v]){
32                     vis[v]=1;
33                     q.push(v);
34                 }
35             }
36         }
37     }
38     return d[2*n]<0x3f3f3f3f;
39 }
40 int main(){
41     scanf("%d%d",&n,&m);
42     memset(head,-1,sizeof(head));
43     for(int i=1;i<=m;i++){
44         scanf("%d%d%d",&x,&y,&z);
45         add(x,y+n,1,z);
46     }
47     for(int i=1;i<=n;i++)add(i+n,i,1,0);
48     ans1=ans2=0;
49     while (spfa()){
50         ans1++;
51         ans2+=d[2*n];
52         for(int i=2*n;i>1;i=edge[from[i]^1].to){
53             edge[from[i]].len--;
54             edge[from[i]^1].len++;
55         }
56     }
57     printf("%d %d",ans1,ans2);
58 } 
View Code

 

posted @ 2019-11-10 16:22  PYWBKTDA  阅读(87)  评论(0编辑  收藏  举报