Codeforces Fox And Dinner(最大流)

抄了个DINIC的模板,然后模拟一下。

#include <bits/stdc++.h>
using namespace std;
const int maxn=80005;
const int inf=0x3f3f3f3f;
typedef vector<int> vi;
typedef vector<vi> vii;
bool vis[maxn];
vector<int>odd,even;
vii ans;
void init(){
    for(int i=2;i<maxn;i++)if(!vis[i]){
        for(int j=i*2;j<maxn;j+=i)vis[j]=1;
    }
}
struct Edge{
    int from,to,cap,flow;
    Edge(){}
    Edge(int from,int to,int cap,int flow):from(from),to(to),cap(cap),flow(flow){}
};
struct Dinic{
    int n,m,s,t;
    vector<Edge>edges;
    vector<int>g[205];
    bool vis[205];
    int d[205];
    int cur[205];

    void init(int n){
        this->n=n;
        edges.clear();
        for(int i=0;i<=n;i++)g[i].clear();
    }

    void addedge(int from,int to,int cap){
        edges.push_back(Edge(from,to,cap,0));
        edges.push_back(Edge(to,from,0,0));
        m=edges.size();
        g[from].push_back(m-2);
        g[to].push_back(m-1);
    }

    bool bfs(){
        memset(vis,0,sizeof vis);
        queue<int>q;
        q.push(s);
        d[s]=0;
        vis[s]=1;
        while(!q.empty()){
            int x=q.front();q.pop();
            for(int i=0;i<g[x].size();i++){
                Edge& e=edges[g[x][i]];
                if(!vis[e.to]&&e.cap>e.flow){
                    vis[e.to]=1;
                    d[e.to]=d[x]+1;
                    q.push(e.to);
                }
            }
        }
        return vis[t];
    }

    int dfs(int x,int a){
        if(x==t||a==0)return a;
        int flow=0,f;
        for(int &i=cur[x];i<g[x].size();i++){
            Edge& e=edges[g[x][i]];
            if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0){
                e.flow+=f;
                edges[g[x][i]^1].flow-=f;
                flow+=f;
                a-=f;
                if(a==0)break;
            }
        }
        return flow;
    }

    int maxflow(int s,int t){
        this->s=s;
        this->t=t;
        int flow=0;
        while(bfs()){
            memset(cur,0,sizeof cur);
            flow+=dfs(s,inf);
        }
        return flow;
    }
}solve;

int main()
{
//    freopen("in","r",stdin);
    init();
    int n,a[222];
    while(scanf("%d",&n)>0){
        solve.init(n+1);
        odd.clear();even.clear();
        for(int i=1;i<=n;i++){
            scanf("%d",a+i);
            if(a[i]%2)odd.push_back(i);
            else even.push_back(i);
        }
        if(odd.size()!=even.size()){
            puts("Impossible");
            continue;
        }
        for(int i=0;i<odd.size();i++)solve.addedge(0,odd[i],2);
        for(int i=0;i<even.size();i++)solve.addedge(even[i],n+1,2);
        for(int i=0;i<odd.size();i++)
        for(int j=0;j<even.size();j++)if(!vis[a[odd[i]]+a[even[j]]])solve.addedge(odd[i],even[j],1);
        int MAX=solve.maxflow(0,n+1);
        if(MAX!=n)puts("Impossible");
        else{
            ans.clear();
            vi res;
            bool vis[222];
            memset(vis,0,sizeof vis);
            for(int i=1;i<=n;i++){
                if(vis[i])continue;
                res.clear();
                vis[i]=1;
                int cnt=0;
                res.push_back(i);
                int c=(a[i]%2)?1:-1;
                for(int j=0;j<solve.g[i].size();j++){
                    Edge x=solve.edges[solve.g[i][j]];
                    if(x.flow==c){
                        res.push_back(x.to);
                        vis[x.to]=1;
                        if(++cnt==2)break;
                    }
                }
//                cout<<res.size()<<endl;
//                for(int i=0;i<res.size();i++)printf("%d%c",res[i],i==res.size()-1?‘\n‘:‘ ‘);
                int now=res[res.size()-1];
                while(now){
                    c*=-1;
                    int newnow=0;
                    cnt=0;
                    for(int j=0;j<solve.g[now].size();j++){
                        Edge x=solve.edges[solve.g[now][j]];
                        if(x.flow==c){
                            if(!vis[x.to]){
                                vis[x.to]=1;
                                newnow=x.to;
                                res.push_back(x.to);
                            }
                            if(++cnt==2)break;
                        }
                    }
                    now=newnow;
                }
                ans.push_back(res);
            }
            cout<<ans.size()<<endl;
            for(int i=0;i<ans.size();i++){
                vi x=ans[i];
                cout<<x.size();
                printf(" %d %d",x[1],x[0]);
                for(int j=2;j<x.size();j++)printf(" %d",x[j]);
                puts("");
            }
        }
    }
    return 0;
}

  

时间: 2024-08-07 08:18:07

Codeforces Fox And Dinner(最大流)的相关文章

CF510E. Fox And Dinner

CF510E. Fox And Dinner https://codeforces.com/contest/510 分析: 由于\(a_i>2\), 相邻两个数一定一奇一偶,按奇偶建立二分图. 环上每个点度数都为2,因此只需要找是否每个点都能匹配两个. 建图跑dinic即可. 代码: #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include

网络流(最大流)CodeForces 512C:Fox And Dinner

Fox Ciel is participating in a party in Prime Kingdom. There are n foxes there (include Fox Ciel). The i-th fox is ai years old. They will have dinner around some round tables. You want to distribute foxes such that: Each fox is sitting at some table

CodeForces 510E Fox And Dinner

CodeForces 510E 素数打表+最大流+最大流打印路径 注意到ai (2 ≤ ai ≤ 104).那么题中的所有素数一定是一个奇数和一个偶数的和.那么所有的桌子都是偶环 将所有的偶数点连接超级源点,奇数点连接超级汇点,容量都为2.将所有的偶数点与奇数点间建容量为1的边,若满流,则可以满足条件 画个图可以知道这样建图是正确的→_→,怎么能想到这一点呢?弱不造 #include<cstdio> #include<cstring> #include<algorithm&g

CodeForces Round #290 Fox And Dinner

而是Div2的最后一题,当时打比赛的时候还不会最大流.自己能够把它写出来然后1A还是很开心的. 题意: 有n个不小于2的整数,现在要把他们分成若干个圈.在每个圈中,数字的个数不少于3个,而且相邻的两个数之和是质数. 分析: 因为每个数都不小于2,所以相加得到的质数一定是奇数,那么在某个圈中,一定是奇偶相间的. 也就是 奇数相邻的两个数是偶数,偶数相邻的两个数是奇数. 所以一个圈中的数字一定是偶数个,所有的输入中也必须是偶数和奇数的个数相同才可能有解. 这转化为了二分图匹配,其中X是奇数,Y是偶数

Codeforces 512C Fox And Dinner 奇偶建图 网络流

题目链接:点击打开链接 题意: 给定n个人和其权值. 让人坐到任意多张圆形的桌子上使得任意两个相邻的人权值和为素数,且一张桌子至少3个人 输出桌子数和每张桌子坐的人(输出任意一个具体方案) 思路: 首先人的权值都是>=2的,也是就说组合成的素数一定是奇数 奇数 = 奇数+偶数.所以桌子上的人一定是奇偶交错的,而且一张桌子人数是偶数个(即n必须为偶数,一半是奇数,一半是偶数) 由上得:一个奇数要选择2个偶数,一个偶数要被2个奇数选择. 所以得到一个二部图,X集为奇数,Y集为偶数 网络流: 奇数连源

codeforces 510E. Fox And Dinner 网络流

题目链接 给出n个人, 以及每个人的值, 要求他们坐在一些桌子上面, 每个桌子如果有人坐, 就必须做3个人以上. 并且相邻的两个人的值加起来必须是素数.每个人的值都>=2. 由大于等于2这个条件, 可以知道素数都是奇数, 那么很明显就需要一奇一偶相邻这样做, 那么一个桌子上必定有偶数个人. 一个奇数旁边有两个偶数, 一个偶数旁边有两个奇数. 所以可以先判断n是否为偶数, 如果是奇数直接输出不可能. 然后开始奇偶建边, 源点和奇数建边, 权值为2, 因为一个奇数需要和两个偶数匹配: 偶数和汇点建边

codeforces gym 100357 I (费用流)

题目大意 给出一个或与表达式,每个正变量和反变量最多出现一次,询问是否存在一种方案使得每个或式中有且仅有一个变量的值为1. 解题分析 将每个变量拆成三个点x,y,z. y表示对应的正变量,z表示对应的反变量. 由S向每个点的x部连一条流量为1的边,表示该变量的某个正变量或反变量的取值为1. 由每个点的x部向y部和z部分别连一条流量为1的边,表示每个正变量和反变量仅有一个取值为1. 若某个或式中含有某个变量,则由该变量的y部或z部向或式连一条流量为1的边.表示该变量可以使该或式的结果为1. 由每个

Codeforces Fox and Card Game (贪心,排序)

C. Fox and Card Game time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Fox Ciel is playing a card game with her friend Fox Jiro. There are n piles of cards on the table. And there is a positi

【题解】Red-Blue Graph Codeforces 1288F 上下界费用流

特别有趣的一个题. 很容易想到可能是网络流问题,关键在于如何刻画诸如"Red边比Blue边多"这样的限制. 最后我还是看了题解...很有趣的思路. 对于每条边,假设她连接了左边点u和右边点v,那么: 从u到v连一条容量是1,费用是r的边,如果走了这条边,意味着这条边染Red. 从v到u连一条容量是1,费用是b的边,如果走了这条边,意味着这条边染Blue. 对于左边的有Red限制的点,显然要求这个点"出去的流量"大于"进来的流量",因此从这个点连向