算法:
新建一个源点汇点 st,en,对原来的每个点i,设m(i)=流入i点的流量下限fin-流出i点的流量下限fout,若m(i)>0,连一条<s,i>容量为m(i)的边;若m(i)<0,连一条<i,t>容量为-m(i)的边。然后将原来边的容量变为c<i,j>-b<i,j>,b<i,j>为流量下届。求一次最大流。如果与s和t关联的边全部满流,则可行流存在,且每条边的流量为现在的流量+流量的下界。否则不存在可行流。
我写了一早上,用我的Dinic模板第一次过不了网络流的题(o(╯□╰)o其实我也只做过几道网络流的题啦)
Dinic算法超时,加输入优化还是TLE!
然后改EK算法,加输入优化还是TLE!无奈之下去掉输入优化试一发,诶。。。A了。。。。
纪念一下第一道有上下界的网络流!
- #include<cstdio>
- #include<iostream>
- #include<cstring>
- #include<algorithm>
- #include<queue>
- #define maxn 210
- #define maxm 40010
- #define INF 0x3f3f3f3f
- using namespace std;
- struct node
- {
- int to,v,next;
- }e[maxm<<2];
- int head[maxn],cnt,maxflow[maxn],flow[maxn][maxn],fin[maxn],fout[maxn];
- int st,en,n,full,m,fa[maxn],l[maxm],a[maxm],b[maxm];
- void add(int x,int y,int z)
- {
- e[cnt].to = y;
- e[cnt].v = z;
- e[cnt].next = head[x];
- head[x] = cnt++;
- e[cnt].to = x;
- e[cnt].v = 0;
- e[cnt].next = head[y];
- head[y] = cnt++;
- }
- void init()
- {
- memset(head,-1,sizeof(head));
- cnt = 0;
- st = 0;
- en = n+1;
- memset(fin,sizeof(fin));
- memset(fout,sizeof(fout));
- full = 0;
- }
- int EK()
- {
- int mf = 0;
- memset(flow,sizeof(flow));
- while(1)
- {
- queue<int> q;
- memset(maxflow,sizeof(maxflow));
- maxflow[st] = INF;
- q.push(st);
- while(!q.empty())
- {
- int u = q.front();
- q.pop();
- for(int i=head[u];i!=-1;i=e[i].next)
- {
- int v = e[i].to;
- if(!maxflow[v] && e[i].v>flow[u][v])
- {
- fa[v] = u;
- maxflow[v] = min(maxflow[u],e[i].v-flow[u][v]);
- q.push(v);
- }
- }
- }
- if(maxflow[en]==0)
- break;
- for(int i=en;i!=st;i=fa[i])
- {
- flow[fa[i]][i]+=maxflow[en];
- flow[i][fa[i]]-=maxflow[en];
- }
- mf+=maxflow[en];
- }
- return mf;
- }
- void solve()
- {
- int mf = EK();
- if(mf!=full)
- printf("NO\n");
- else
- {
- printf("YES\n");
- for(int i=0;i<m;i++)
- printf("%d\n",flow[a[i]][b[i]]+l[i]);
- }
- }
- int main()
- {
- int T,c;
- char d;
- scanf("%d",&T);
- while(T--)
- {
- scanf("%d%d",&n,&m);
- init();
- for(int i=0;i<m;i++)
- {
- scanf("%d%d%d%d",&a[i],&b[i],&l[i],&c);
- add(a[i],b[i],c-l[i]);
- fin[b[i]]+=l[i];
- fout[a[i]]+=l[i];
- }
- for(int i=1;i<=n;i++)
- {
- int tmp = fin[i]-fout[i];
- if(tmp>0)
- {
- add(st,i,tmp);
- full += tmp;
- }
- else
- add(i,-tmp);
- }
- solve();
- }
- return 0;
- }