传送门
这题真有意思。。。
先是有一个点T的我怀疑人生。
然后学大佬们封装了我的dinic就莫名其妙的过了???
所以说锅给谁好呢?
给dinic吧。。。
解法就是先求出一段可行流,然后从t到s加一条容量为inf的边将能缩回去的都缩回去。
代码:
#include
#define ll long long
#define inf 0x3f3f3f3f
#define N 100005
#define M 2000010
using namespace std;
#define rep(i,st,ed) for(register int i=st,i##end=ed;i<=i##end;++i)
#define drep(i,st,ed) for(register int i=st,i##end=ed;i>=i##end;--i)
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
ll ans;
int S,T;
struct Node{int v,next,c;};
struct Max_Flow{
int n,cur[N],first[N],d[N],cnt;
Node e[M];
inline void add_edge(int u,int v,int c){e[++cnt].v=v,e[cnt].next=first[u],e[cnt].c=c,first[u]=cnt;}
inline void add(int u,int v,int c){add_edge(u,v,c),add_edge(v,u,0);}
inline bool bfs(){
rep(i,1,n)d[i]=-1;
queue<int>q;
q.push(S),d[S]=0;
while(!q.empty()){
int x=q.front();
q.pop();
for(int i=first[x];i;i=e[i].next){
int v=e[i].v;
if(e[i].c&&d[v]==-1){
d[v]=d[x]+1;
if(v==T)return true;
q.push(v);
}
}
}
return false;
}
inline int dfs(int x,int f){
if(x==T||!f)return f;
int flow=f,tmp;
for(int &i=cur[x];i;i=e[i].next){
int v=e[i].v;
if(e[i].c&&d[v]==d[x]+1){
tmp=dfs(v,min(e[i].c,flow));
if(!tmp)d[v]=-1;
e[i].c-=tmp,e[i^1].c+=tmp,flow-=tmp;
if(!flow)return f;
}
}
return f-flow;
}
inline void solve(){while(bfs()){rep(i,1,n)cur[i]=first[i];ans+=dfs(S,inf);}}
}Dinic;
int sum[N];
int main(){
Dinic.cnt=1;
int n=read(),m=read(),ss=read(),tt=read();
S=n+1,T=n+2,Dinic.n=T;
rep(i,1,m){
int u=read(),v=read(),down=read(),up=read();
sum[u]-=down,sum[v]+=down,Dinic.add(u,v,up-down);
}
rep(i,1,n){
if(sum[i]>0)Dinic.add(S,i,sum[i]);
if(sum[i]<0)ans+=sum[i],Dinic.add(i,T,-sum[i]);
}
Dinic.solve(),Dinic.add(tt,ss,inf),Dinic.solve();
if(ans){cout<<"please go home to sleep";return 0;}
cout<return 0;
}