BZOJ2893: 征服王
来源:互联网 发布:手机淘宝体验中心在哪 编辑:程序博客网 时间:2024/04/28 14:20
题目链接
【分析】
首先,第一步tarjan缩点还是很容易想到的。
一个点至少要经过一次,所以拆点,连两条边,第一条流量为1,费用为1,第二条流量为INF,费用为0。
连通块之间连边,流量为INF,费用为0。 若块x可作为起点,则由S–>x’连边,流量为INF,费用为0。若可作为终点,则由x”–>T连边,流量为INF,费用为0。 增广次数即为答案。
(又是一道把我心态做崩的题。。一开始打成了每条边走一次╮(╯▽╰)╭。。三个小时才发现错了。。蠢得可以。)
【代码】
#include <cstdio>#include <iostream>#include <queue>#include <vector>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#define N 2005#define M 100005#define INF 1000000000using namespace std;typedef long long ll;typedef pair<ll,ll> pa;int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();} return x*f;}int n,m,cnt=1,S,T,ans,CaseT,Cnt,num_s,num_t,ind,scc,Ans,sum;int b[M],p[N],nextedge[M],w[M],c[M];int B[20005],P[N],Next[20005];int Dis[N],Pre[N],Dfn[N],Low[N];int aa[N],bb[N];bool Flag[N],Instack[N],Mark[N];int Belong[N];void Add(int x,int y,int z,int cost){ cnt++; b[cnt]=y; nextedge[cnt]=p[x]; p[x]=cnt; w[cnt]=z; c[cnt]=cost;}void Anode(int x,int y,int z,int cost){ Add(x,y,z,cost);Add(y,x,0,-cost);}void Ins(int x,int y){ Cnt++; B[Cnt]=y; Next[Cnt]=P[x]; P[x]=Cnt;}void Input_Init(){ n=read();m=read();num_s=read(),num_t=read(); Cnt=ind=scc=ans=Ans=sum=0; for(int i=1;i<=n;i++) P[i]=0; for(int i=1;i<=num_s;i++) aa[i]=read(); for(int i=1;i<=num_t;i++) bb[i]=read(); for(int i=1;i<=m;i++) { static int x,y,z; x=read(),y=read(); Ins(x,y); }}stack<int>st;void Tarjan(int x){ Dfn[x]=Low[x]=++ind; st.push(x); Instack[x]=1; for(int i=P[x];i;i=Next[i]) { int v=B[i]; if(!Dfn[v]) { Tarjan(v); Low[x]=min(Low[x],Low[v]); } else if(Instack[v]) Low[x]=min(Low[x],Dfn[v]); } if(Low[x]==Dfn[x]) { int now=-1;scc++; while(now!=x) { now=st.top();st.pop(); Instack[now]=0; Belong[now]=scc; } }}void Get_Scc(){ for(int i=1;i<=n;i++) Dfn[i]=0; for(int i=1;i<=n;i++) if(!Dfn[i]) Tarjan(i); }void Build_Graph(){ T=scc<<1|1; cnt=1; for(int i=0;i<=T;i++) p[i]=Pre[i]=0; for(int i=1;i<=n;i++) Mark[i]=0; for(int i=1;i<=num_s;i++) Anode(0,Belong[aa[i]],INF,0); for(int i=1;i<=num_t;i++) Anode(Belong[bb[i]]+scc,T,INF,0); for(int i=1;i<=n;i++) for(int j=P[i];j;j=Next[j]) if(Belong[i]!=Belong[B[j]]) Anode(Belong[i]+scc,Belong[B[j]],INF,0); for(int i=1;i<=scc;i++) { Anode(i,i+scc,INF,0); Anode(i,i+scc,1,-1); }}bool Bfs(){ queue<int>q; q.push(S); for(int i=0;i<=T;i++) Dis[i]=INF; Dis[S]=0; while(!q.empty()) { int k=q.front();q.pop();Flag[k]=0; for(int i=p[k];i;i=nextedge[i]) { int v=b[i],f=w[i]; if(Dis[v]>Dis[k]+c[i]&&f) { Dis[v]=Dis[k]+c[i]; Pre[v]=i; if(!Flag[v]) { Flag[v]=1; q.push(v); } } } } return Dis[T]!=INF;}bool Mcf(){ int Maxf=INF; for(int i=Pre[T];i;i=Pre[b[i^1]]) Maxf=min(Maxf,w[i]); for(int i=Pre[T];i;i=Pre[b[i^1]]) { w[i]-=Maxf,w[i^1]+=Maxf; ans-=c[i]*Maxf; }}void MCF(){ while(Bfs()) { int pre=ans; Mcf(); if(pre==ans) break; else Ans++; } if(ans!=scc) printf("no solution\n"); else printf("%d\n",Ans);}int main(){ CaseT=read(); while(CaseT--) { Input_Init(); Get_Scc(); Build_Graph(); MCF(); } return 0;}
0 0
- BZOJ2893: 征服王
- BZOJ2893: 征服王
- 征服
- 2893: 征服王 tarjan+最小流
- 【BZOJ】【P2893】【征服王】【题解】【缩点费用流】
- “使命、征服”
- 征服一切
- 征服MFC
- 不可征服
- 征服机会
- 征服 Redis
- 征服 Redis
- 征服 Nginx
- 征服 Kestrel
- 征服 Redis
- 征服 Redis
- 征服 Redis
- 征服 TIME_WAIT !
- Android开发模式之--MVP设计模式一
- AmigoDateTimePicker 和 DateTimePicker 反射
- 【hpuoj】模电问题
- BZOJ 1455 罗马游戏
- VS2013 MFC使用位图美化对话框
- BZOJ2893: 征服王
- 完数
- 安装px4编译环境时出现CMAKE Error:错误
- 第一讲
- Android Studio Can't update: no tracked branch
- 阮一峰的网络日志
- 关于完数,亏数和盈数
- 龙虎榜这玩意本质上就是杀猪榜(鬼才信专栏)
- word-wrap与word-break的区别