1 条题解

  • 0
    @ 2026-8-27 14:51:11

    10510^5,非常稀疏的图,可以尝试 Dinic 网络流。

    因为每条边都要被线路覆盖一次,所以考虑上下界网络流建边下界为 11,上界为无限大。

    然后因为线路可以从任意点开始和结束,于是考虑建超级源点和汇点,超级源点向每个点,每个点向超级汇点都连一条下界为 00,上界为无限大的边。

    直接跑上下界最小流就做完了。

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    int n,m,s,t,S,T;
    int head[100010],to[1000010],nxt[1000010],val[1000010],tot=1;
    void add(int u,int v,int w){
    	to[++tot]=v,val[tot]=w;
    	nxt[tot]=head[u];
    	head[u]=tot;
    }
    int maxflow,dis[100010],now[100010];
    bool vis[100010];
    bool bfs(){
    	queue<int>q;
    	memset(vis,0,sizeof vis);
    	vis[s]=1,dis[s]=0,now[s]=head[s];
    	q.push(s);
    	while(!q.empty()){
    		int u=q.front();
    		q.pop();
    		for(int i=head[u];i;i=nxt[i]){
    			if(vis[to[i]] || !val[i]) continue;
    			now[to[i]]=head[to[i]];
    			dis[to[i]]=dis[u]+1,vis[to[i]]=1;
    			q.push(to[i]);
    			if(to[i]==t) return 1;
    		}
    	}
    	return 0;
    }
    int dinic(int x,int flow){
    	if(x==t) return flow;
    	int rest=flow;
    	for(int i=now[x];i && rest;i=nxt[i]){
    		now[x]=i;
    		if(dis[to[i]]!=dis[x]+1 || !val[i]) continue;
    		int v=dinic(to[i],min(rest,val[i]));
    		if(!v) dis[to[i]]=0;
    		val[i]-=v,val[i^1]+=v;
    		rest-=v;
    	}
    	return flow-rest;
    }
    int V[100010],_val[1000010];
    signed main() {
    	cin>>n;
    	S=0,T=n+1; 
    	s=n+2,t=n+3;
    	for(int i=1;i<n;i++){
    		int u,v;
    		cin>>u>>v;
    		u++,v++;
    		add(u,v,1e16-1),add(v,u,0);
    		V[v]++,V[u]--;
    	}
    	for(int i=1;i<=n;i++) add(S,i,1e16),add(i,S,0),add(i,T,1e16),add(T,i,0);
    	int sum=0;
    	for(int i=0;i<=n+1;i++) if(V[i]>0) add(s,i,V[i]),add(i,s,V[i]),sum+=V[i];else if(V[i]<0) add(i,t,-V[i]),add(t,i,-V[i]);
    	add(T,S,1e15),add(S,T,0);
    	int flow=0;
    	while(bfs()) while(flow=dinic(s,1e18)) maxflow+=flow;
    	if(maxflow<sum) cout<<"A clever xzy~~~";
    	else{
    		for(int i=1;i<=tot;i++) _val[i]=val[i];
    		s=T,t=S;
    		int ans=val[tot];
    		val[tot]=val[tot^1]=0;
    		maxflow=0;
    		while(bfs()) while(flow=dinic(s,1e18)) maxflow+=flow;
    		cout<<ans-maxflow<<" ";
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    6129
    时间
    1000ms
    内存
    250MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者