2 条题解

  • 0
    @ 2026-2-7 20:33:08
    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1210;
    typedef long long LL;
    struct edge
    {
    	LL x,cap,rev;
    };
    int g[N][N];
    vector<edge> e[N];
    int n,m,s,t;
    int d[N],it[N];
    void add(int a,int b,int c)
    {
    	e[a].push_back({b,c,e[b].size()});
    	e[b].push_back({a,0,e[a].size() - 1});
    }
    void bfs()
    {
    	memset(d,-1,sizeof d);
    	queue<int> q;
    	d[s] = 0;
    	q.push(s);
    	while(!q.empty())
    	{
    		int u = q.front();
    		q.pop();
    		for(auto t : e[u])
    			if(t.cap > 0 && d[t.x] < 0) d[t.x] = d[u] + 1,q.push(t.x);
    	}
    }
    LL dfs(int u,LL f)
    {
    	if(u == t) return f;
    	for(int &i = it[u]; i < e[u].size(); i ++)
    	{
    		edge &t = e[u][i]; 
    		if(d[u] < d[t.x] && t.cap > 0)
    		{
    			LL d = dfs(t.x,min(f,t.cap));
    			if(d > 0)
    			{
    				t.cap -= d;
    				e[t.x][t.rev].cap += d;
    				return d;
    			}
    		}
    	}
    	return 0;
    }
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin.tie(0);
    	cin>>n>>m>>s>>t;
    	for(int i = 1; i <= m; i ++)
    	{
    		int x,y,z;
    		cin>>x>>y>>z;
    		g[x][y] += z;
    	}
    	LL flow = 0;
    	for(int i = 28; i >= 0; i -= 4)
    	{
    		for(int x = 1; x <= n; x ++)
    			for(int y = 1; y <= n; y ++)
    				if(g[x][y] >= (1 << i)) add(x,y,g[x][y]),g[x][y] = 0;
    		while(1)
    		{
    			bfs();
    			if(d[t] < 0) break;
    			memset(it,0,sizeof it);
    			LL d = dfs(s,1e18);
    			while(d > 0)
    			{
    				flow += d;
    				d = dfs(s,1e18);
    			}
    		}
    	}
    	cout<<flow<<endl;
    	return 0;
    }
    
    • 0
      @ 2025-10-8 16:50:02
      #include<bits/stdc++.h>//44分的代码(只优化了当前弧),正常dinic28分
      using namespace std;
      typedef long long LL;
      const int N=1300,M=250000;
      struct node{int x,y;LL f; int pre;}a[M];int alen,last[N],cur[N];
      void ins(int x,int y,LL f)
      {
          alen++;a[alen]=node{x,y,f,last[x]};last[x]=alen;
          alen++;a[alen]=node{y,x,0,last[y]};last[y]=alen;
      }
      
      int h[N],st,ed,n,m;
      bool bfs()
      {
      	deque<int>q;q.clear();
          memset(h,0,sizeof(h));h[st]=1;
          q.push_back(st);
          while(!q.empty())
          {
              int x=q.front();q.pop_front();
              for(int k=last[x];k>0;k=a[k].pre)if(a[k].f)
              {
                  int y=a[k].y;
                  if(h[y]==0)
                  {
                      h[y]=h[x]+1;
                      q.push_back(y);
                  }
              }
          }
          return h[ed]>0;
      }
      
      LL dinic(int x,LL f)
      {
          if(x==ed)return f;
          LL sx=0;
          for(int k=cur[x];k;k=a[k].pre)if(a[k].f)
          {
              int y=a[k].y;
              cur[x]=k;//k之前的边对于x已经没有意义 
              if(h[y]==h[x]+1)
              {
                  LL sy=dinic(y,min(a[k].f,f-sx));
                  a[k].f-=sy;a[k^1].f+=sy;
                  sx+=sy;if(sx==f)return f;
              }
          }
          if(sx==0)h[x]=0;
          return sx;
      }
      int main()
      {
          scanf("%d%d%d%d",&n,&m,&st,&ed);
          alen=1;memset(last,0,sizeof(last));
          for(int i=1;i<=m;i++)
      	{
              int x,y;LL f;scanf("%d%d%lld",&x,&y,&f);
              ins(x,y,f);
          }
          //dinic过程:如果存在层次图就探索存在的流
          LL s=0;
          while( bfs() )
          {
          	memcpy(cur,last,sizeof(int)*(n+2)); 
              s+=dinic(st,(LL)1<<62);
          }
          printf("%lld",s);
          return 0;
      }


      bool _Start;// by Lofty
      #include<queue>
      #include<cstdio>
      #include<cstring>
      #include<iostream>
      #include<algorithm>
      namespace IO
      {
      	#define TP template<typename T>
      	#define TP_ template<typename T,typename ... T_>
      	#ifdef DEBUG
      	#define gc() (getchar())
      	#else
      	char buf[1<<20],*p1,*p2;
      	#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
      	#endif
      	#ifdef DEBUG
      	void pc(const char &c)
      	{
      		putchar(c);
      	}
      	#else
      	char pbuf[1<<20],*pp=pbuf;
      	void pc(const char &c)
      	{
      		if(pp-pbuf==1<<20)
      			fwrite(pbuf,1,1<<20,stdout),pp=pbuf;
      		*pp++=c;
      	}
      	struct IO{~IO(){fwrite(pbuf,1,pp-pbuf,stdout);}}_;
      	#endif
      	TP void read(T &x)
      	{
      		x=0;static int f;f=0;static char ch;ch=gc();
      		for(;ch<'0'||ch>'9';ch=gc())ch=='-'&&(f=1);
      		for(;ch>='0'&&ch<='9';ch=gc())x=(x<<1)+(x<<3)+(ch^48);
      		f&&(x=-x);
      	}
      	TP void write(T x)
      	{
      		if(x<0)
      			pc('-'),x=-x;
      		static T sta[35],top;top=0;
      		do
      			sta[++top]=x%10,x/=10;
      		while(x);
      		while(top)
      			pc(sta[top--]^48);
      	}
      	TP_ void read(T &x,T_&...y){read(x);read(y...);}
      	TP void writeln(const T x){write(x);pc('\n');}
      	TP void writesp(const T x){write(x);pc(' ');}
      	TP_ void writeln(const T x,const T_ ...y){writesp(x);writeln(y...);}
      	TP void debugsp(const T x){fprintf(stderr,"%d ",x);}
      	TP void debug(const T x){fprintf(stderr,"%d\n",x);}
      	TP_ void debug(const T x,const T_...y){debugsp(x);debug(y...);}
      	TP inline T max(const T &a,const T &b){return a>b?a:b;}
      	TP_ inline T max(const T &a,const T_&...b){return max(a,max(b...));} 
      	TP inline T min(const T &a,const T &b){return a<b?a:b;}
      	TP_ inline T min(const T &a,const T_&...b){return min(a,min(b...));}
      	TP inline void swap(T &a,T &b){static T t;t=a;a=b;b=t;}
      	TP inline T abs(const T &a){return a>0?a:-a;}
      	#undef TP
      	#undef TP_
      }
      using namespace IO;
      using std::cerr;
      using PII=std::pair<int,int>;
      using LL=long long;
      constexpr int N=5e3+10,M=3e5+10,inf=0x3f3f3f3f;
      int n,m,st,ed;
      LL w[N];
      int h[N],gap[N<<1],cur[N];
      struct edge
      {
      	int y;LL f;int other;
      };
      std::vector<edge>a[N];
      inline void ins(int x,int y,LL f)
      {
      	a[x].push_back({y,f,(int)a[y].size()});
      	a[y].push_back({x,0,(int)a[x].size()-1});
      }
      struct cmp
      {
      	inline bool operator()(const int &x,const int &y)const
      	{
      		return h[x]<h[y];//队内高度不会改变,必须先出队再改,优先队列只在插入和出队时排序
      	}
      };
      bool bfs()//给所有点一个初始的高度,选择最短路的原因是推流的点最少
      {
      	static std::queue<int>q;
      	memset(h,0x3f,sizeof(h));
      	h[ed]=1;
      	q.push(ed);
      	while(q.size())
      	{
      		int x=q.front();q.pop();
      		for(auto k:a[x])
      		{
      			int y=k.y;
      			if(a[y][k.other].f&&h[y]>h[x]+1)
      			{
      				h[y]=h[x]+1;
      				q.push(y);
      			}
      		}
      	}
      	return h[st]!=h[0];
      }
      bool inq[N];
      std::priority_queue<int,std::vector<int>,cmp>q;//按高度排序的大根堆
      inline void push(int x)//对 x 点的余流推流出去
      {
      	for(int &i=cur[x];i<(int)a[x].size();i++)//当前弧优化,若保留了当前弧,说明目前余流不足,还可以需要再推流
      	{
      		edge &k=a[x][i];
      		int y=k.y;
      		if(k.f&&h[y]==h[x]-1)//可以流且是一条合法的推流路径
      		{
      			LL f=min(w[x],k.f);
      			w[x]-=f;w[y]+=f;
      			k.f-=f;
      			a[y][k.other].f+=f;
      			if(y!=st&&y!=ed&&!inq[y])//加入队列。注意起点和终点不能入队,因为起点有无限余流,终点只接收,没有余流
      				q.push(y),inq[y]=1;
      			if(!w[x])//没有余流可推了,自然要提前结束
      				return ;//这里必须是 return 而不是 break!否则当仍有边可推流时当前弧重置,优化就是假的!(@WisNourx_ 就是这个**写错)
      		}
      	}
      	cur[x]=0;//如果还有余流,就再重新遍历,对应下面改变高度,流向新的路径
      }
      inline void relabel(int x)//重新给一个高度
      {
      	h[x]=inf;
      	for(auto k:a[x])
      		if(k.f&&h[k.y]+1<h[x])//往尽量低处流,因为最低点是终点
      			h[x]=h[k.y]+1;
      }
      LL HLPP()
      {
      	if(!bfs())//提前给定高度,加速推流,否则需要再推流时给定,增加遍历数量
      		return 0;
      	for(int i=1;i<=n;i++)
      		if(h[i]<inf)
      			++gap[h[i]];//gap 优化,若一个高度已经全部流完,更高的是找不到低处流的
      						//并且 gap 需要开到 2n-1,最极端的情况可能会全部流回起点
      	h[st]=n;//若其他点流完找不到低处,就要流回起点方向,为防可能流向其他方向,应定为 n,这样其他点在初始情况下是不可能高于起点的
      	for(auto &k:a[st])//在起点做一次无限流量的推流
      	{
      		int y=k.y;
      		if(k.f&&h[y]<inf)
      		{
      			LL f=k.f;
      			w[st]-=f;w[y]+=f;
      			k.f-=f;
      			a[y][k.other].f+=f;
      			if(y!=st&&y!=ed&&!inq[y])//加入队列。注意起点和终点不能入队,因为起点有无限余流,终点只接收,没有余流
      				q.push(y),inq[y]=1;
      		}
      	}
      	while(q.size())
      	{
      		int x=q.top();q.pop();inq[x]=0;
      		push(x);
      		if(w[x])
      		{
      			if(--gap[h[x]]<=0)//没有该高度了
      				for(int i=1;i<=n;i++)
      					if(i!=st&&i!=ed&&h[i]>h[x]&&h[i]<n+1)//那么比它更高的就没有低处流了,流回起点
      						h[i]=n+1;
      			relabel(x);++gap[h[x]];
      			q.push(x);inq[x]=1;
      		}
      	}
      	return w[ed];
      }
      bool _End;
      int main()
      {
      //	fprintf(stderr,"%.2 MBlf\n",(&_End-&_Start)/1048576.0);
      	read(n,m,st,ed);
      	for(int i=1,x,y,f;i<=m;i++)
      	{
      		read(x,y,f);
      		ins(x,y,f);
      	}
      	writeln(HLPP());
      	return 0;
      }
      



      HLPP 预流推进 - Lofty

      • 1

      信息

      ID
      392
      时间
      1500ms
      内存
      512MiB
      难度
      9
      标签
      递交数
      168
      已通过
      14
      上传者