CodeForces 1484C Basic Diplomacy 网络流模板题

题目链接
题意

某君有n朋友,他需要和她们玩耍m天,每一天都有一些人可以和他玩,某君每天只能选择和一个人玩,如果和一个人玩超过m/2上取整次,就会不高兴,问是否有不会不高兴的选择方案,有的话输出方案

思路

裸的最大流,建立s,t,日期点,朋友点。s向所有日期连边,权1,对于每一天,将日期点向当天可以游戏的朋友连边,权1,所有朋友点向t连边,权为m/2上取整。

跑最大流,如果maxflow和日期数相等,那么就是有方案。至于输出方案,我们跑完dinic后,日期和朋友间连的正向边如果权变成了0,说明这个日期选的是这个朋友,输出即可。

教训/收获

为什么DIV2的C题会有网络流?
在这里插入图片描述

代码
#include<cstdio>
#include<iostream>
#include<iomanip>
#include<map>
#include<unordered_map>
#include<string>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib> 
#include<chrono>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
//#define int long long
//#define double long double
using namespace std;
	typedef long long ll;
	const int maxn=200505;
    const int maxe=800050;
	const int inf=0x3f3f3f3f;
	int n,m,k;
	int head[maxn],cnt;
	struct Edge{
		int v;
		int w;
		int next;
	}edge[maxe];

	int deep[maxn];
	int now[maxe];


	void init(){
		memset(head,-1,sizeof(head));
		cnt=0;
		return ;	
	}
	inline void add(int u,int v,int w){
  		edge[cnt].v=v;
		edge[cnt].w=w;
		edge[cnt].next=head[u];
		head[u]=cnt++;
	}
	
	inline void addd(int u,int v,int w){
		//cout<<u<<" "<<v<<" "<<w<<endl; 
		add(u,v,w);
		add(v,u,0);
	}
	
	inline bool bfs(int s,int t){
    	memset(deep,0x3f,sizeof(deep));
    	queue<int>q;
    	q.push(s);deep[s] = 0;now[s] = head[s];
    	while(q.size()){
        	int x = q.front();q.pop();
        	for(int i=head[x];i!=-1;i=edge[i].next){
        	    int y=edge[i].v;
         	    if(edge[i].w>0&&deep[y]==inf){
         	    	q.push(y);
        	        now[y]=head[y];
         	       	deep[y]=deep[x]+1;
        	        if(y==t)	return 1;
				}
        	}
    	}
    	return 0;
	}

	ll dfs(int x,int t,int flow){
    	if(x==t)	return flow;
    	ll ans = 0,k,i;
    	for(i=now[x];i!=-1&&flow;i=edge[i].next){
        	now[x]=i;
        	int y=edge[i].v;
        	if(edge[i].w>0&&(deep[y]==deep[x]+1)){
        	    k=dfs(y,t,min(flow,edge[i].w));
         		if(!k)	deep[y]=inf;
            	edge[i].w-=k;
            	edge[i^1].w+=k;
            	ans+=k;
            	flow-=k;
        	}
    	}
    	return ans;
	}	

	ll dinic(int s,int t){
		ll maxflow=0;
    	while(bfs(s,t))
    	    maxflow+=dfs(s,t,inf);
    	return maxflow;
	}
    signed main(){
		IOS
		#ifndef ONLINE_JUDGE
		    freopen("D:\\_ACM_code\\IO\\in.txt","r",stdin);
		    freopen("D:\\_ACM_code\\IO\\out.txt","w",stdout);
        #endif
		int tn;
		cin>>tn;
		while(tn--){
            int s=200001,t=s+1;
            init();
			cin>>n>>m;
            for(int i=1;i<=m;i++){
                addd(s,i,1);
                int t;
                cin>>t;
                while(t--){
                    int v;
                    cin>>v;
                    addd(i,v+100000,1);
                } 
            }
            int li=(m-1)/2+1;
            for(int i=1;i<=n;i++)
                addd(i+100000,t,li);
            int ans=dinic(s,t);
            //cout<<ans<<endl;
            if(ans==m) {
                cout<<"YES"<<endl;
                for(int i=1;i<=m;i++){
                    for(int j=head[i];~j;j=edge[j].next){
                        if(edge[j].w==0){
                            cout<<edge[j].v-100000<<' ';
                            break;
                        }
                    }
                }
                cout<<endl;
            }
            else    cout<<"NO"<<endl;
		}
	} 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Codeforces的动态规划单中,有基础DP、优化递推式、进阶DP、数据结构、优先队列、并查集、图论、最短路、最小生成树、数论、二分搜索等不同类型的目。 代码中的内容是一个动态规划的例子,它采用了一个二维数组来存储中间结果,并通过递推的方式计算最优解。这个例子中,它使用了一个for循环嵌套来遍历数组,并利用状态转移方程更新数组中的值。最后输出的是计算得到的最优解。 要注意的是,这段代码是一个完整的程序,需要依赖于一些特定的输入数据才能正确运行。如果你想在Codeforces上找到更多的动态规划目,可以访问它们的官方网站并浏览库。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [牛客练习_21314:codeforces (动态规划+01背包)](https://blog.csdn.net/qq_45750296/article/details/109587967)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [leetcode双人赛-acm-challenge-workbook:acm-挑战-工作簿](https://download.csdn.net/download/weixin_38701340/19923844)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Codeforces Round #750 (Div. 2)E(动态规划)](https://blog.csdn.net/m0_51506743/article/details/121083708)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值