码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj2561:最小割

时间:2016-01-15 20:33:24      阅读:233      评论:0      收藏:0      [点我收藏+]

标签:

从中午就开始WA,然后到傍晚的时候不屈不饶还是继续WA,然后肉眼查错实在找不到错误,就写了个数据生成器,把中间过程和师兄的都输出对比,然后出在了最觉得不会错的地方OrzOrz。以后要是WA就用这种方法吧。终于A了OrzOrzOrz。。。

-----------------------------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#include<vector>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define rep(i,n) for(int i=1;i<=n;i++)
#define clr(x,c) memset(x,c,sizeof(x))
#define down(i,n) for(int i=n;i;i--)
const int inf=0x3f3f3f3f;
int read(){
 int x=0;char c=getchar();
 while(!isdigit(c)) c=getchar();
 while(isdigit(c)){
  x=x*10+c-‘0‘;
  c=getchar();
 }
 return x;
}


struct edge{
 int to,cap;
 edge *next,*rev;
};
edge e[800000],*pt=e,*cur[20005],*p[20005],*head[20005];
int d[20005],cnt[20005];
void add(int u,int v,int d){
 pt->to=v;pt->cap=d;pt->next=head[u];head[u]=pt++;
}
void adde(int u,int v,int d){
 add(u,v,d);
 add(v,u,0);
 head[u]->rev=head[v];
 head[v]->rev=head[u];
}
struct Edge{
 int from,to,w;
 bool operator<(const Edge&rhs)const{
   return w<rhs.w;}
};
vector<Edge>edges;


int maxflow(int s,int t,int n){
 clr(d,0);
 clr(cnt,0);
 cnt[0]=n;
 int flow=0,a=inf,x=s;
 while(d[s]<n){
  edge *ee;
  for(ee=cur[x];ee;ee=ee->next){
   if(ee->cap>0&&d[ee->to]+1==d[x]) break;
  }
  if(ee){
   p[ee->to]=cur[x]=ee;
   a=min(a,ee->cap);
   x=ee->to;
   if(x==t){
    while(x!=s){
     p[x]->cap-=a;
     p[x]->rev->cap+=a;
     x=p[x]->rev->to;
    }
    flow+=a;
    a=inf;
   }
  }else{
   if(!--cnt[d[x]]) break;
   d[x]=n;
   for(ee=head[x];ee;ee=ee->next){
    if(ee->cap>0&&d[ee->to]+1<d[x]){
     d[x]=d[ee->to]+1;
     cur[x]=ee;
    }
   }
   cnt[d[x]]++;
   if(x!=s) x=p[x]->rev->to;
  }
 }
 return flow;
}


int main(){
 int n=read(),m=read(),ans=0;
 rep(i,m){
  Edge o;
  o.from=read(),o.to=read(),o.w=read();
  edges.push_back(o);
  //edges.push_back(Edge(read(),read(),read()));WA在这里Orz
 }
 int s=read(),t=read(),L=read();
 sort(edges.begin(),edges.end());
 //for(int i=0;i<m;i++) printf("%d ",edges[i].w);
 for(int i=0;i<m;i++){
  Edge &o=edges[i];
  if(o.w>=L) break;
  adde(o.from,o.to,1);
  adde(o.to,o.from,1);
 }
 ans+=maxflow(s,t,n);
 //printf("%d\n",ans);
 clr(head,0);clr(cur,0);pt=e;
 for(int i=m-1;i>=0;i--){
  Edge &o=edges[i];
  if(o.w<=L) break;
  adde(o.from,o.to,1);
  adde(o.to,o.from,1);
 }
 ans+=maxflow(s,t,n);
 printf("%d\n",ans);
 return 0;
}

-----------------------------------------------------------------------------------------

2561: 最小生成树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1094  Solved: 542
[Submit][Status][Discuss]

Description

 给定一个边带正权的连通无向图G=(V,E),其中N=|V|,M=|E|,N个点从1到N依次编号,给定三个正整数u,v,和L (u≠v),假设现在加入一条边权为L的边(u,v),那么需要删掉最少多少条边,才能够使得这条边既可能出现在最小生成树上,也可能出现在最大生成树上?

 

Input

 

 

 

 

 

  第一行包含用空格隔开的两个整数,分别为N和M;
  接下来M行,每行包含三个正整数u,v和w表示图G存在一条边权为w的边(u,v)。
  最后一行包含用空格隔开的三个整数,分别为u,v,和 L;
  数据保证图中没有自环。
 

Output

 输出一行一个整数表示最少需要删掉的边的数量。

Sample Input

3 2
3 2 1
1 2 3
1 2 2

Sample Output

1

HINT

对于20%的数据满足N ≤ 10,M ≤ 20,L ≤ 20;

  对于50%的数据满足N ≤ 300,M ≤ 3000,L ≤ 200;

  对于100%的数据满足N ≤ 20000,M ≤ 200000,L ≤ 20000。

Source

[Submit][Status][Discuss]

bzoj2561:最小割

标签:

原文地址:http://www.cnblogs.com/fighting-to-the-end/p/5134299.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!