http://codeforces.com/problemset/problem/700/C
题意:n个点m条边,从s到t,让你删掉最多两条边,让s和t不通,让花费最小。
题解:首先要说一下,我真是太菜了,看见这题又是一脸蒙逼啊,其实这题点1000,边30000,nm的复杂度完全能过,如果我发现了这个,可能会有思路呢,知道了这个的话,就可以先找一条路出来,因为有路,所以为了不通,肯定要删除上面一条边,所以就是n的枚举删边,删边之后呢,如何找删第二条边,那么肯定要再搜一次看能不能找到一条路径咯,这是m的复杂度,如果没找到,就是删一条,如果找到了,怎么办,总不能再枚举再搜把,如果要删除第二条路里的一条边,从而让s和t分开,没有别的路径从t到达s,那么这条边肯定是桥,所以我们可以在删边之后,m的复杂度tarjan求桥,然后找第二条路径,然后n的复杂度枚举路径找上面是否有桥
代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#pragma comment(linker,"/STACK:102400000,102400000")
using namespace std;
#define MAX 1005
#define MAXN 60005
#define maxnode 15
#define sigma_size 30
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lrt rt<<1
#define rrt rt<<1|1
#define middle int m=(r+l)>>1
#define LL long long
#define ull unsigned long long
#define mem(x,v) memset(x,v,sizeof(x))
#define lowbit(x) (x&-x)
#define pii pair
#define bits(a) __builtin_popcount(a)
#define mk make_pair
#define limit 10000
//const int prime = 999983;
const int INF = 0x3f3f3f3f;
const LL INFF = 0x3f3f;
const double pi = acos(-1.0);
const double inf = 1e18;
const double eps = 1e-4;
const LL mod = 1e9+7;
const ull mx = 133333331;
/*****************************************************/
inline void RI(int &x) {
char c;
while((c=getchar())<'0' || c>'9');
x=c-'0';
while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
}
/*****************************************************/
struct Edge{
int v,next,c;
}edge[MAXN];
int head[MAX];
int tot;
int s,t;
int vis[MAX];
int dfn[MAX];
int low[MAX];
int bridge[MAXN];
int Index;
void init(){
mem(head,-1);
mem(vis,0);
tot=0;
}
void add_edge(int a,int b,int c){
edge[tot]=(Edge){b,head[a],c};
head[a]=tot++;
}
bool dfs(int u,int fa,int del,vector<int>& path){
vis[u]=1;
if(u==t) return true;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(v==fa||(i>>1)==del) continue;
if(!vis[v]&&dfs(v,u,del,path)){
path.push_back(i>>1);
return true;
}
}
return false;
}
void tarjan(int u,int fa,int del){
dfn[u]=low[u]=++Index;
int flag=0;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if((i>>1)==del) continue;
if(v==fa&&!flag){
flag=1;
continue;
}
if(!dfn[v]){
tarjan(v,u,del);
low[u]=min(low[v],low[u]);
if(low[v]>dfn[u]) bridge[i>>1]=1;
}
else low[u]=min(dfn[v],low[u]);
}
}
int main(){
//freopen("in.txt","r",stdin);
int n,m;
while(cin>>n>>m){
cin>>s>>t;
init();
for(int i=0;iint a,b,c;
scanf("%d%d%d",&a,&b,&c);
add_edge(a,b,c);
add_edge(b,a,c);
}
vector<int> path;
if(!dfs(s,-1,-1,path)){
printf("0\n0\n");
}
else{
int ans=2e9+5;
vector<int> ret;
for(int i=0;i0);
mem(bridge,0);
mem(vis,0);
Index=0;
//cout<
for(int j=1;j<=n;j++){
if(!dfn[j]) tarjan(j,-1,path[i]);
}
vector<int> tmp;
if(!dfs(s,-1,path[i],tmp)){
if(ans>edge[path[i]*2].c){
ans=edge[path[i]*2].c;
ret.clear();
ret.push_back(path[i]+1);
}
}
else{
for(int j=0;jif (bridge[tmp[j]]){
if(ans>edge[path[i]*2].c+edge[tmp[j]*2].c){
ans=edge[path[i]*2].c+edge[tmp[j]*2].c;
ret.clear();
ret.push_back(path[i]+1);
ret.push_back(tmp[j]+1);
}
}
}
}
}
if(ans>2e9) cout<<-1<else{
cout<for(int i=0;iprintf("%d",ret[i]);
if(i==ret.size()-1) cout<else cout<<" ";
}
}
}
}
return 0;
}