给定一个边带正权的连通无向图G=(V,E),其中N=|V|,M=|E|,N个点从1到N依次编号,给定三个正整数u,v,和L (u≠v),假设现在加入一条边权为L的边(u,v),那么需要删掉最少多少条边,才能够使得这条边既可能出现在最小生成树上,也可能出现在最大生成树上?
标签:
从中午就开始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;
}
-----------------------------------------------------------------------------------------
给定一个边带正权的连通无向图G=(V,E),其中N=|V|,M=|E|,N个点从1到N依次编号,给定三个正整数u,v,和L (u≠v),假设现在加入一条边权为L的边(u,v),那么需要删掉最少多少条边,才能够使得这条边既可能出现在最小生成树上,也可能出现在最大生成树上?
输出一行一个整数表示最少需要删掉的边的数量。
对于20%的数据满足N ≤ 10,M ≤ 20,L ≤ 20;
对于50%的数据满足N ≤ 300,M ≤ 3000,L ≤ 200;
对于100%的数据满足N ≤ 20000,M ≤ 200000,L ≤ 20000。
标签:
原文地址:http://www.cnblogs.com/fighting-to-the-end/p/5134299.html