当前位置: 首页 > news >正文

codeforces-510E Fox And Dinner(带限制的二分图多重匹配+奇偶建图+打印路径)

题意:

有n个fox,分别有一个年龄为a[i]。 现在要将n个fox分配入座,但要求两两相邻的fox的年龄和为质数。一桌(环形桌)至少要有三个fox。求要分几桌才能满足上述要求,并打印每桌有几个fox以及每个fox的具体id。(n <= 200, 2 <= a[i] <= 1e4)

思路:

由于年龄最小是2,所以两两相加为质数只可能是一奇一偶相加所得,所以安排座位就是一个奇数两旁是偶数,一个偶数两旁是奇数,一个桌子上的fox个数是偶数个。所以我们可以把奇数和偶数分到二分图的两部,同样得到特判:当且仅当两部的元素个数相等有解。我们将源点S向奇数部建有向边容量为2,偶数部向汇点T建有向边容量为2,然后就是奇偶建边,如果两个数之和是质数就建一条从奇数到偶数的有向边容量为1。然后如果求得最大流等于n则有解,否则没有。为什么能用最大流做呢,最大流==n就代表A部的每个点恰好匹配B部的两个点,B部的每个点也恰好匹配A部的两个点。然后根据网络流流量的性质就可以得出所有的路径,打印出来即可。

代码:

#include <algorithm>    
#include <iostream>    
#include <string.h>  
#include <vector>  
#include <cstdio>    
#include <queue>    
using namespace std;    
const int inf = 0x3f3f3f3f;    
const int maxn = 205;    
const int maxm = maxn*maxn;  
struct node{int w; int v, next;} edge[maxm];    
int pre[maxn], rec[maxn], head[maxn], gap[maxn], now[maxn];    
int dis[maxn];  
int n, no, up;    
int S, T;   
queue<int> q;  
inline void add(int u, int v, int w)    
{    
    edge[no].v = v; edge[no].w = w;    
    edge[no].next = head[u]; head[u] = no++;    
    edge[no].v = u; edge[no].w = 0;    
    edge[no].next = head[v]; head[v] = no++;    
}    
inline void pre_init()    
{    
    no = 0;  
    memset(head, -1, sizeof head);    
}    
void init(int S, int T)    
{    
    memset(gap, 0, sizeof gap);    
    memset(dis, 0x3f, sizeof dis);    
    for(int i = 0; i <= up; ++i)     
    now[i] = head[i];  
    while(!q.empty()) q.pop();    
    dis[T] = 0; q.push(T);    
    while(!q.empty())   
    {    
        int tp = q.front(); q.pop();    
        ++gap[dis[tp]];    
        int k = head[tp];    
        while(k != -1)    
        {    
            if(dis[edge[k].v] == inf && edge[k^1].w)    
            {    
                dis[edge[k].v] = dis[tp]+1;    
                q.push(edge[k].v);    
            }    
            k = edge[k].next;    
        }    
    }    
}    
int SAP(int S, int T)    
{  
    int ans = 0, flow = inf;  
    int top = S;    
    pre[S] = S; init(S, T);    
    while(dis[S] < up)  
    {  
        if(top == T)    
        {    
            ans += flow;    
            while(top != S)  
            {    
                edge[rec[top]].w -= flow;    
                edge[rec[top]^1].w += flow;    
                top = pre[top];    
            }    
            flow = inf;    
        }    
        int k = now[top];    
        while(k != -1)    
        {    
            int v = edge[k].v;    
            if(edge[k].w && dis[top] == dis[v]+1)    
            {    
                flow = min(flow, edge[k].w);    
                pre[v] = top; rec[v] = k;    
                now[top] = k; top = v;    
                break;    
            }    
            k = edge[k].next;    
        }    
        if(k == -1)    
        {    
            int mind = up;    
            if(--gap[dis[top]] == 0) break;  
            int k = now[top] = head[top];  
            while(k != -1)    
            {    
                if(edge[k].w && mind>dis[edge[k].v]) mind = dis[edge[k].v];    
                k = edge[k].next;    
            }    
            ++gap[dis[top] = mind+1];    
            top = pre[top];    
        }    
    }    
    return ans;    
}  
int a[maxn];
bool isprime[20005], vis[maxn];  
vector<int> g[maxn], vt[maxn];
void prime_init()
{
	memset(isprime, 0, sizeof isprime);
	isprime[1] = true;
	for(int i = 2; i*i <= 20000; ++i)
	if(!isprime[i])
	for(int j = i*i; j <= 20000; j+=i)
	isprime[j] = true;
}
bool mapping()  
{ 
	int ttx = 0;
    for(int i = 1; i <= n; ++i)    
    {    
        scanf("%d", &a[i]);
        if(a[i]&1) add(S, i, 2), ++ttx;
        else add(i, T, 2);
        for(int j = 1; j < i; ++j)
        if(!isprime[a[i]+a[j]])
        {
        	if(a[i]&1) add(i, j, 1);
        	else add(j, i, 1);
		}
    }  
    return ttx*2 == n;
}  
void dfs(int id, int u)
{
	vis[u] = true;
	vt[id].push_back(u);
	for(int i = 0; i < g[u].size(); ++i)
	{
		int v = g[u][i];
		if(vis[v]) continue;
		dfs(id, v);
	}
}
void work()
{
	memset(vis, 0, sizeof vis);
	for(int i = 1; i <= n; ++i) g[i].clear();
	for(int i = 1; i <= n; ++i)
	{
		if(!(a[i]&1)) continue;
		for(int k = head[i]; k+1; k = edge[k].next)
		{
			int v = edge[k].v;
			if(v == S) continue;
			if(!edge[k].w && !(k&1))
			{
				g[i].push_back(v);
				g[v].push_back(i);
			}
		}
	}
	int cnt = 0;
	for(int i = 1; i <= n; ++i)
	{
		if(vis[i]) continue;
		++cnt; vt[cnt].clear();
		dfs(cnt, i);
	}
	printf("%d\n", cnt);
	for(int i = 1; i <= cnt; ++i)
	{
		printf("%d", vt[i].size());
		for(int j = 0; j < vt[i].size(); ++j)
		printf(" %d", vt[i][j]);
		printf("\n");
	}
}
int main()    
{  
    while(~scanf("%d", &n))    
    {    
        up = n+2, S = 0, T = n+1;  
        pre_init(); 
		prime_init();   
        if(!mapping()) puts("Impossible");
        else if(SAP(S, T) != n) puts("Impossible");
        else work(); 
    }
    return 0;    
}


继续加油~

相关文章:

  • C-Cleaning Pipes(判断两线段相交+二分图判定) 2015-2016 Northwestern European Regional Contest (NWERC 2015)
  • eclipse the user operation is waiting for building workspace to complete
  • 2-SAT 题目整理
  • 64位windows2003 未在本地计算机上注册 microsoft.jet.oledb.4.0 提供程序
  • HDU-5950 Recursive sequence(矩阵乘法)
  • “互联网+”引发IT人才招工荒-新华网安徽频道
  • Java从文件读入以及读出至文件
  • HDU-5963 朋友(树上博弈)
  • HDU 6005 Pandaland(无向图最小环)
  • Cura源码在Ubuntu15.04上编译脚本(成功)
  • SPOJ - CHICAGO 106 miles to Chicago(乘积最短路)
  • HTML5之FileReader的使用
  • LeetCode 202 Happy Number(floyd判圈算法(龟兔赛跑算法))
  • css3 中text-align:justify
  • HDU-1503 Advanced Fruits(LCS)
  • 【140天】尚学堂高淇Java300集视频精华笔记(86-87)
  • export和import的用法总结
  • Mysql5.6主从复制
  • Nacos系列:Nacos的Java SDK使用
  • Node 版本管理
  • SQLServer插入数据
  • weex踩坑之旅第一弹 ~ 搭建具有入口文件的weex脚手架
  • 包装类对象
  • 初探 Vue 生命周期和钩子函数
  • 从 Android Sample ApiDemos 中学习 android.animation API 的用法
  • 基于 Ueditor 的现代化编辑器 Neditor 1.5.4 发布
  • 基于webpack 的 vue 多页架构
  • 计算机在识别图像时“看到”了什么?
  • 使用SAX解析XML
  • 适配iPhoneX、iPhoneXs、iPhoneXs Max、iPhoneXr 屏幕尺寸及安全区域
  • 微信小程序--------语音识别(前端自己也能玩)
  • ​Distil-Whisper:比Whisper快6倍,体积小50%的语音识别模型
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • (1)安装hadoop之虚拟机准备(配置IP与主机名)
  • (42)STM32——LCD显示屏实验笔记
  • (python)数据结构---字典
  • (Redis使用系列) SpringBoot 中对应2.0.x版本的Redis配置 一
  • (SpringBoot)第二章:Spring创建和使用
  • (分布式缓存)Redis分片集群
  • (六)Hibernate的二级缓存
  • (全注解开发)学习Spring-MVC的第三天
  • (图)IntelliTrace Tools 跟踪云端程序
  • (一)ClickHouse 中的 `MaterializedMySQL` 数据库引擎的使用方法、设置、特性和限制。
  • (转)eclipse内存溢出设置 -Xms212m -Xmx804m -XX:PermSize=250M -XX:MaxPermSize=356m
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • .NET CLR Hosting 简介
  • .NET Compact Framework 3.5 支持 WCF 的子集
  • .NET 编写一个可以异步等待循环中任何一个部分的 Awaiter
  • .Net(C#)常用转换byte转uint32、byte转float等
  • .Net接口调试与案例
  • .NET连接数据库方式
  • @Transient注解
  • [ web基础篇 ] Burp Suite 爆破 Basic 认证密码
  • [ 隧道技术 ] cpolar 工具详解之将内网端口映射到公网
  • [\u4e00-\u9fa5] //匹配中文字符