1 条题解

  • 0
    @ 2026-8-28 22:02:53

    编号为 1n1\sim nnn 个人两两之间进行比赛,一共进行 n(n1)2\frac{n(n-1)}{2} 场,只有胜负两种结果,不会出现平局。

    mm 场已经结束,第 ii 场比赛中,人 WiW_i 战胜了人 LiL_i

    请升序输出所有可能单独获得冠军的人,即该人的胜场数可能比其他任何人的胜场数都多。

    2n50,0mn(n1)22\le n\le 50,0\le m\le \frac{n(n-1)}{2}

    我们假设第 ii 个人已经赢了 aia_i 场,输了 bib_i 场。

    我们考虑枚举获得冠军的人 ii,那我们肯定让他赢 k=(n1)bik=(n-1)-b_i 场,于是其他人不能赢超过 k1k-1 场。

    于是我们建 n(n1)2\frac{n(n-1)}{2} 个点表示每一场比赛,源点向比赛的点连容量为 11 的边,mm 场确定的比赛连向胜者的点。对于和 ii 有关的未确定的比赛连向 ii,其余的连向比赛的两个人的点(这些边的容量都为 11)。

    然后 ii 向汇点连容量为 kk 的边,其余人的点向汇点连容量为 k1k-1 的边。

    最后看最大流是不是等于 n(n1)2\frac{n(n-1)}{2} 即可。

    #include<bits/stdc++.h>
    #define FL(i,a,b) for(int i=(a);i<=(b);i++)
    #define FR(i,a,b) for(int i=(a);i>=(b);i--)
    #define ll long long
    #define ull unsigned long long
    #define ld long double
    #define PII pair<int,int>
    using namespace std;
    const int MAXN = 50 + 10;
    const int MR = 3e3 + 10;
    const int MAXM = 2e4 + 10;
    const int inf = 0x3f3f3f3f;
    
    int n,m;
    int S,T,tot;
    PII c[MR];
    int a[MAXN],b[MAXN];
    int ID[MAXN][MAXN];
    bool us[MAXN][MAXN];
    int head[MR],now[MR],cnt=1;
    int dis[MR];
    struct node{
    	int v,w,nxt;
    }e[MAXM];
    void Add_edge(int u,int v,int w){
    	e[++cnt].v=v;
    	e[cnt].w=w;
    	e[cnt].nxt=head[u];
    	head[u]=cnt;
    }
    
    bool bfs(){
    	FL(i,S,T) dis[i]=inf;
    	queue<int>q;
    	now[S]=head[S],dis[S]=0,q.push(S);
    	while(!q.empty()){
    		int u=q.front();
    		q.pop();
    		for(int i=head[u];i;i=e[i].nxt){
    			int v=e[i].v,w=e[i].w;
    			if(w&&dis[v]==inf){
    				now[v]=head[v],dis[v]=dis[u]+1,q.push(v);
    				if(v==T) return 1;
    			}
    		}
    	}
    	return 0;
    }
    
    int dfs(int u,int flow){
    	if(u==T) return flow;
    	int res=0;
    	for(int i=now[u];i;i=e[i].nxt){
    		int v=e[i].v;
    		now[u]=i;
    		if(e[i].w&&(dis[v]==dis[u]+1)){
    			int tmp=dfs(v,min(flow,e[i].w));
    			if(!tmp) dis[v]=inf;
    			e[i].w-=tmp,e[i^1].w+=tmp;
    			flow-=tmp,res+=tmp;
    		}
    	}
    	return res;
    }
    int dinic(){
    	int res=0;
    	while(bfs()) res+=dfs(S,inf);
    	return res;
    }
    
    int main(){
    	scanf("%d%d",&n,&m),S=0,T=n+n*(n-1)/2+1,tot=n;
    	FL(i,1,n) FL(j,i+1,n) ID[i][j]=ID[j][i]=++tot;
    	FL(i,1,m){
    		scanf("%d%d",&c[i].first,&c[i].second);
    		a[c[i].first]++,b[c[i].second]++;
    		us[c[i].first][c[i].second]=us[c[i].second][c[i].first]=1;
    	}
    	FL(id,1,n){
    		int k=n-1-b[id];
    		cnt=1;
    		FL(i,S,T) head[i]=0;
    		FL(i,1,n) FL(j,i+1,n) Add_edge(S,ID[i][j],1),Add_edge(ID[i][j],S,0);
    		FL(i,1,m) Add_edge(ID[c[i].first][c[i].second],c[i].first,1),Add_edge(c[i].first,ID[c[i].first][c[i].second],0);
    		FL(i,1,n){
    			FL(j,i+1,n){
    				if(us[i][j]) continue;
    				if(i==id||j==id)
    					Add_edge(ID[i][j],id,1),Add_edge(id,ID[i][j],0);
    				else
    					Add_edge(ID[i][j],i,1),Add_edge(i,ID[i][j],0),
    					Add_edge(ID[i][j],j,1),Add_edge(j,ID[i][j],0);
    			}
    		}
    		FL(i,1,n) Add_edge(i,T,k-1+(id==i)),Add_edge(T,i,0);
    		if(dinic()==n*(n-1)/2) printf("%d ",id);
    	}
    }
    
    • 1

    信息

    ID
    12404
    时间
    2000ms
    内存
    1024MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者