loj 1167(二分+最大流)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=26881

思路:我们可以二分最大危险度,然后建图,由于每个休息点只能用一次,就要拆点,将每个休息点拆点,边容量为1,代表只能使用一次,然后跑最大流验证。

  1 #include<iostream>

  2 #include<cstdio>

  3 #include<cstring>

  4 #include<algorithm>

  5 #include<queue>

  6 #include<cmath>

  7 using namespace std;

  8 #define MAXN 222

  9 #define MAXM 222222

 10 #define inf 1<<30

 11 #define FILL(a,b) memset(a,b,sizeof(a))

 12 

 13 struct Edge{

 14     int v,cap,next;

 15 }edge[MAXM];

 16 

 17 int n,m,vs,vt,k,NV,NE;

 18 int head[MAXN];

 19 

 20 void Insert(int u,int v,int cap)

 21 {

 22     edge[NE].v=v;

 23     edge[NE].cap=cap;

 24     edge[NE].next=head[u];

 25     head[u]=NE++;

 26 

 27     edge[NE].v=u;

 28     edge[NE].cap=0;

 29     edge[NE].next=head[v];

 30     head[v]=NE++;

 31 }

 32 

 33 int level[MAXN],gap[MAXN];

 34 void bfs(int vt)

 35 {

 36     FILL(level,-1);

 37     FILL(gap,0);

 38     queue<int>que;

 39     level[vt]=0;

 40     gap[0]++;

 41     que.push(vt);

 42     while(!que.empty()){

 43         int u=que.front();

 44         que.pop();

 45         for(int i=head[u];i!=-1;i=edge[i].next){

 46             int v=edge[i].v;

 47             if(level[v]!=-1)continue;

 48             level[v]=level[u]+1;

 49             gap[level[v]]++;

 50             que.push(v);

 51         }

 52     }

 53 }

 54 

 55 int pre[MAXN],cur[MAXN];

 56 int SAP(int vs,int vt)

 57 {

 58     bfs(vt);

 59     memcpy(cur,head,sizeof(head));

 60     int u=pre[vs]=vs,aug=inf,maxflow=0;

 61     gap[0]=NV;

 62     while(level[vs]<NV){

 63         bool flag=false;

 64         for(int &i=cur[u];i!=-1;i=edge[i].next){

 65             int v=edge[i].v;

 66             if(edge[i].cap>0&&level[u]==level[v]+1){

 67                 flag=true;

 68                 aug=min(aug,edge[i].cap);

 69                 pre[v]=u;

 70                 u=v;

 71                 if(v==vt){

 72                     maxflow+=aug;

 73                     for(u=pre[u];v!=vs;v=u,u=pre[u]){

 74                         edge[cur[u]].cap-=aug;

 75                         edge[cur[u]^1].cap+=aug;

 76                     }

 77                     aug=inf;

 78                 }

 79                 break;

 80             }

 81         }

 82         if(flag)continue;

 83         int minlevel=NV;

 84         for(int i=head[u];i!=-1;i=edge[i].next){

 85             int v=edge[i].v;

 86             if(edge[i].cap>0&&level[v]<minlevel){

 87                 minlevel=level[v];

 88                 cur[u]=i;

 89             }

 90         }

 91         if(--gap[level[u]]==0)break;

 92         level[u]=minlevel+1;

 93         gap[level[u]]++;

 94         u=pre[u];

 95     }

 96     return maxflow;

 97 }

 98 

 99 struct Path{

100     int u,v,d;

101 }path[MAXM];

102 

103 void Build(int limit)

104 {

105     NE=0;

106     memset(head,-1,sizeof(head));

107     vs=0,vt=2*n+3,NV=2*n+4;

108     for(int i=0;i<m;i++){

109         if(path[i].d<=limit)Insert(path[i].u+n+2,path[i].v,1);

110     }

111     for(int i=1;i<=n;i++)Insert(i,i+n+2,1);

112     Insert(vs,vs+n+2,11);

113     Insert(n+1,vt,11);

114 }

115 

116 

117 int main()

118 {

119     int _case,u,v,d,low,high,mid,ans,t=1;

120     scanf("%d",&_case);

121     while(_case--){

122         scanf("%d%d",&n,&m);

123         low=inf,high=0;

124         for(int i=0;i<m;i++){

125             scanf("%d%d%d",&path[i].u,&path[i].v,&path[i].d);

126             if(path[i].u>path[i].v)swap(path[i].u,path[i].v);

127             //cout<<path[i].u<<"&&&&"<<path[i].v<<endl;

128             low=min(low,path[i].d);

129             high=max(high,path[i].d);

130         }

131        // cout<<low<<"**"<<high<<endl;

132         scanf("%d",&k);

133         ans=inf;

134         while(low<=high){

135             mid=(low+high)>>1;

136             Build(mid);

137             if(SAP(vs,vt)>=k){

138                 ans=mid;

139                 high=mid-1;

140             }else

141                 low=mid+1;

142         }

143         printf("Case %d: ",t++);

144         if(ans!=inf){

145             printf("%d\n",ans);

146         }else

147             puts("no solution");

148     }

149     return 0;

150 }
View Code

 

你可能感兴趣的:(最大流)