BZOJ2055: 80人环游世界

 

题解:

总算A掉了,各种蛋疼。。。

int main()
{
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    n=read();m=read();s=0;t=2*n+m+1;ss=t+1;tt=t+2;sss=tt+1;
    insert(s,sss,0,m,0);
    for1(i,n)insert(sss,i,0,inf,0);
    for1(i,n){int x=read();insert(i,i+n,x,x,0);}
    for1(i,n)for2(j,i+1,n){int x=read();if(x!=-1)insert(i+n,j,0,inf,x);}
    for1(i,n)insert(i+n,t,0,inf,0);
    insert(t,s,0,inf,0);
    mcf();
    printf("%d\n",mincost);
    return 0;
}

s是附加源,sss是真正的源,t是真正的汇。这样构图就好了,但我们还有下界限制,那再来个ss,tt。。。居然还是费用流。。。然后这题就做完了
因为我们只需要最小费用,所以我们只需求出可行流&最小费用即可。

关于下界的处理我直接写在insert函数里。。。导致慢成翔。。。

代码:

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<iostream>
 7 #include<vector>
 8 #include<map>
 9 #include<set>
10 #include<queue>
11 #include<string>
12 #define inf 1000000000
13 #define maxn 200000
14 #define maxm 200000
15 #define eps 1e-10
16 #define ll long long
17 #define pa pair<int,int>
18 #define for0(i,n) for(int i=0;i<=(n);i++)
19 #define for1(i,n) for(int i=1;i<=(n);i++)
20 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
21 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
22 #define for4(i,x) for(int i=head[x],y;i;i=e[i].next)
23 #define mod 1000000007
24 using namespace std;
25 inline int read()
26 {
27     int x=0,f=1;char ch=getchar();
28     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
29     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
30     return x*f;
31 }
32 int n,m,k,mincost,tot=1,s,t,ss,tt,sss,head[maxn],d[maxn],from[2*maxm];
33 bool v[maxn];
34 queue<int>q;
35 struct edge{int from,go,next,v,c;}e[2*maxm];
36 void ins(int x,int y,int v,int c)
37 {
38     e[++tot]=(edge){x,y,head[x],v,c};head[x]=tot;
39     e[++tot]=(edge){y,x,head[y],0,-c};head[y]=tot;
40 }
41 void insert(int x,int y,int l,int r,int c)
42 {
43     ins(ss,y,l,c);ins(x,tt,l,0);ins(x,y,r-l,c);
44 }
45 bool spfa()
46 {
47     for (int i=0;i<=sss;i++){v[i]=0;d[i]=inf;}
48     q.push(ss);d[ss]=0;v[ss]=1;
49     while(!q.empty())
50     {
51         int x=q.front();q.pop();v[x]=0;
52         for (int i=head[x],y;i;i=e[i].next)
53          if(e[i].v&&d[x]+e[i].c<d[y=e[i].go])
54          {
55             d[y]=d[x]+e[i].c;from[y]=i;
56             if(!v[y]){v[y]=1;q.push(y);}
57          }
58     }
59     return d[tt]!=inf;
60 }
61 void mcf()
62 {
63     mincost=0;
64     while(spfa())
65     {
66         int tmp=inf;
67         for(int i=from[tt];i;i=from[e[i].from]) tmp=min(tmp,e[i].v);
68         mincost+=d[tt]*tmp;
69         for(int i=from[tt];i;i=from[e[i].from]){e[i].v-=tmp;e[i^1].v+=tmp;}
70     }
71 }
72 int main()
73 {
74     freopen("input.txt","r",stdin);
75     freopen("output.txt","w",stdout);
76     n=read();m=read();s=0;t=2*n+m+1;ss=t+1;tt=t+2;sss=tt+1;
77     insert(s,sss,0,m,0);
78     for1(i,n)insert(sss,i,0,inf,0);
79     for1(i,n){int x=read();insert(i,i+n,x,x,0);}
80     for1(i,n)for2(j,i+1,n){int x=read();if(x!=-1)insert(i+n,j,0,inf,x);}
81     for1(i,n)insert(i+n,t,0,inf,0);
82     insert(t,s,0,inf,0);
83     mcf();
84     printf("%d\n",mincost);
85     return 0;
86 }
View Code

 UPD:把边合并了之后用时成了1/4

代码:

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<iostream>
 7 #include<vector>
 8 #include<map>
 9 #include<set>
10 #include<queue>
11 #include<string>
12 #define inf 1000000000
13 #define maxn 200000
14 #define maxm 200000
15 #define eps 1e-10
16 #define ll long long
17 #define pa pair<int,int>
18 #define for0(i,n) for(int i=0;i<=(n);i++)
19 #define for1(i,n) for(int i=1;i<=(n);i++)
20 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
21 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
22 #define for4(i,x) for(int i=head[x],y;i;i=e[i].next)
23 #define mod 1000000007
24 using namespace std;
25 inline int read()
26 {
27     int x=0,f=1;char ch=getchar();
28     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
29     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
30     return x*f;
31 }
32 int n,m,k,mincost,tot=1,s,t,ss,tt,sss,head[maxn],d[maxn],from[2*maxm],in[maxn];
33 bool v[maxn];
34 queue<int>q;
35 struct edge{int from,go,next,v,c;}e[2*maxm];
36 void ins(int x,int y,int v,int c)
37 {
38     e[++tot]=(edge){x,y,head[x],v,c};head[x]=tot;
39     e[++tot]=(edge){y,x,head[y],0,-c};head[y]=tot;
40 }
41 void insert(int x,int y,int l,int r,int c)
42 {
43     in[y]+=l;
44     in[x]-=l;
45     ins(x,y,r-l,c);
46 }
47 void build()
48 {
49     for0(i,sss)if(in[i]>0)ins(ss,i,in[i],0);
50     else if(in[i]<0)ins(i,tt,-in[i],0);
51 }
52 bool spfa()
53 {
54     for (int i=0;i<=sss;i++){v[i]=0;d[i]=inf;}
55     q.push(ss);d[ss]=0;v[ss]=1;
56     while(!q.empty())
57     {
58         int x=q.front();q.pop();v[x]=0;
59         for (int i=head[x],y;i;i=e[i].next)
60          if(e[i].v&&d[x]+e[i].c<d[y=e[i].go])
61          {
62             d[y]=d[x]+e[i].c;from[y]=i;
63             if(!v[y]){v[y]=1;q.push(y);}
64          }
65     }
66     return d[tt]!=inf;
67 }
68 void mcf()
69 {
70     mincost=0;
71     while(spfa())
72     {
73         int tmp=inf;
74         for(int i=from[tt];i;i=from[e[i].from]) tmp=min(tmp,e[i].v);
75         mincost+=d[tt]*tmp;
76         for(int i=from[tt];i;i=from[e[i].from]){e[i].v-=tmp;e[i^1].v+=tmp;}
77     }
78 }
79 int main()
80 {
81     freopen("input.txt","r",stdin);
82     freopen("output.txt","w",stdout);
83     n=read();m=read();s=0;t=2*n+m+1;ss=t+1;tt=t+2;sss=tt+1;
84     insert(s,sss,0,m,0);
85     for1(i,n)insert(sss,i,0,inf,0);
86     for1(i,n){int x=read();insert(i,i+n,x,x,0);}
87     for1(i,n)for2(j,i+1,n){int x=read();if(x!=-1)insert(i+n,j,0,inf,x);}
88     for1(i,n)insert(i+n,t,0,inf,0);
89     insert(t,s,0,inf,0);
90     build();
91     mcf();
92     printf("%d\n",mincost);
93     return 0;
94 }
View Code

 

2055: 80人环游世界

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 116  Solved: 75
[Submit][Status]

Description

Input

第一行两个正整数N,M。第二行有N个不大于M正整数,分别表示V1,V2......VN。接下来有N ¡ 1行。第i行有N ¡ i个整数,该行的第j个数表示从第i个国家到第i + j个国家的机票费(如果该值等于¡1则表示这两个国家间没有通航)。

Output

在第一行输出最少的总费用。

Sample Input

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

Sample Output

27

HINT

1<= N < =100 1<= M <= 79

posted @ 2014-12-21 13:50  ZYF-ZYF  Views(298)  Comments(0Edit  收藏  举报