BZOJ 3546: [ONTAK2010]Life of the Party

Description

一个二分图最大匹配,求出所有关键点.\(n,m\leqslant 10^4,k\leqslant 10^5\)

Solution

二分图匹配.

2015年国家队论文集 - 浅谈图的匹配算法及其应用 陈胤伯

Code

/**************************************************************
    Problem: 3546
    User: BeiYu
    Language: C++
    Result: Accepted
    Time:1844 ms
    Memory:14436 kb
****************************************************************/

#include <bits/stdc++.h>
using namespace std;

#define mpr make_pair

const int N = 20050;
const int M = 100050;
const int oo = 0x3fffffff;

inline int in(int x=0,char s=getchar()) { while(s>‘9‘||s<‘0‘)s=getchar();
    while(s>=‘0‘&&s<=‘9‘)x=x*10+s-‘0‘,s=getchar();return x; }

struct Network {
    struct Edge { int fr,to,fl; }edge[M<<3];
    vector<int> g[N];
    int S,T,flow,ce,k;
    int d[N],p[N],cur[N];

    void AddEdge(int fr,int to,int fl) {
        edge[ce++]=(Edge) { fr,to,fl },edge[ce++]=(Edge) { to,fr,0 };
        g[fr].push_back(ce-2),g[to].push_back(ce-1);
    }
    int BFS() {
        memset(d,0xff,sizeof(d));
        queue<int> q;
        d[S]=0,q.push(S);
        for(int x;!q.empty();) {
            x=q.front(),q.pop();
            for(int i=0;i<(int)g[x].size();i++) {
                Edge &e=edge[g[x][i]];
                if(e.fl && d[e.to]==-1) d[e.to]=d[x]+1,q.push(e.to);
            }
        }return d[T]!=-1;
    }
    int Dinic() {
        for(int x;BFS();) {
            for(k=0,x=S,memset(cur,0,sizeof(cur));;) {
                if(x==T) {
                    int mine=0,minf=oo;
                    for(int i=0;i<k;i++) if(edge[p[i]].fl<minf) minf=edge[p[i]].fl,mine=i;
                    for(int i=0;i<k;i++) edge[p[i]].fl-=minf,edge[p[i]^1].fl+=minf;
                    k=mine,x=edge[p[mine]].fr,flow+=minf;
                }
                for(int &i=cur[x];i<(int)g[x].size();i++) {
                    Edge &e=edge[g[x][i]];
                    if(e.fl && d[e.to]==d[x]+1) break;
                }if(cur[x]<(int)g[x].size()) {
                    p[k++]=g[x][cur[x]],x=edge[g[x][cur[x]]].to;
                } else {
                    if(!k) break;
                    d[x]=-1,x=edge[p[--k]].fr;
                }
            }
        }return flow;
    }
}py;

struct Gph {
    vector<int> g[N];
    int vis[N];

    void clr() { memset(vis,0,sizeof(vis));for(int i=0;i<N;i++) g[i].clear(); }
    void AddEdge(int fr,int to) { g[fr].push_back(to); }
    void DFS(int u) {
        if(vis[u]) return;vis[u]=1;
        for(int i=0;i<(int)g[u].size();i++) DFS(g[u][i]);
    }
    void outE(int n) {
        for(int i=1;i<=n;i++) {
            cout<<i<<" --> ";
            for(int j=0;j<(int)g[i].size();j++) cout<<g[i][j]<<" ";cout<<endl;
        }
    }
}pn;

int n,m,k,cp;
pair<int,int> pr[N];
int L[N];

int main() {
    n=in(),m=in(),k=in();
    for(int i=1;i<=k;i++) {
        int u=in(),v=in();
        py.AddEdge(u,v+n,1);
    }
    py.S=0,py.T=n+m+1;
    for(int i=1;i<=n;i++) py.AddEdge(py.S,i,1);
    for(int i=1;i<=m;i++) py.AddEdge(i+n,py.T,1);
    py.Dinic();
//  cout<<py.Dinic()<<endl;
    for(int i=0;i<2*k;i+=2) if(py.edge[i^1].fl)
        pr[++cp]=mpr(py.edge[i].fr,py.edge[i].to);
//  cout<<"---"<<endl;

    memset(L,0,sizeof(L));
    for(int i=1;i<=cp;i++) L[pr[i].first]=pr[i].second;
    for(int i=0;i<2*k;i+=2) {
        if(L[py.edge[i].fr]!=py.edge[i].to) pn.AddEdge(py.edge[i].fr,py.edge[i].to);
        else pn.AddEdge(py.edge[i].to,py.edge[i].fr);
    }
    for(int i=1;i<=n;i++) if(!L[i]) pn.DFS(i);
    for(int i=1;i<=n;i++) if(!pn.vis[i]) printf("%d\n",i);

//  pn.outE(n+m);
//  cout<<"---"<<endl;
    pn.clr();
    memset(L,0,sizeof(L));
    for(int i=1;i<=cp;i++) L[pr[i].second]=pr[i].first;
    for(int i=1;i<2*k;i+=2) {
        if(L[py.edge[i].fr]!=py.edge[i].to) pn.AddEdge(py.edge[i].fr,py.edge[i].to);
        else pn.AddEdge(py.edge[i].to,py.edge[i].fr);
    }
    for(int i=1;i<=m;i++) if(!L[i+n]) pn.DFS(i+n);
    for(int i=1;i<=m;i++) if(!pn.vis[i+n]) printf("%d\n",i);
//  pn.outE(n+m);
    return 0;
}

  

时间: 2024-08-25 03:01:11

BZOJ 3546: [ONTAK2010]Life of the Party的相关文章

bzoj 3551: [ONTAK2010]Peaks加强版

Description [题目描述]同3545 Input 第一行三个数N,M,Q. 第二行N个数,第i个数为h_i 接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径. 接下来Q行,每行三个数v x k,表示一组询问.v=v xor lastans,x=x xor lastans,k=k xor lastans.如果lastans=-1则不变. Output 同3545 Sample Input Sample Output HINT [数据范围]同3545 Source

BZOJ 3550 ONTAK2010 Vacation 单纯形

题目大意:给定一个长度为3n的区间,要求选一些数,且任意一段长度为n的区间内最多选k个数,求选择数的和的最大值 单纯形直接搞 注意一个数只能被选一次 因此要加上xi<=1这个约束条件 不明白3n还有k<=10是为何... #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define EPS 1

bzoj 3551 [ONTAK2010]Peaks加强版(kruskal,主席树,dfs序)

Description [题目描述]同3545 Input 第一行三个数N,M,Q. 第二行N个数,第i个数为h_i 接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径. 接下来Q行,每行三个数v x k,表示一组询问.v=v xor lastans,x=x xor lastans,k=k xor lastans.如果lastans=-1则不变. Output 同3545 [思路] Kruskal+主席树+dfs序 一个叫kruskal重构树的方法QWQ.在kruskal合

BZOJ 3550 [ONTAK2010]Vacation 线性规划

题意:链接 方法:线性规划 解析: 这是一道蛮简单的单纯性线性规划. 首先我们设Xi表示第i个数是否选择. 则显然 X1+X2+...+Xn<=k X2+X3...+Xn+1<=k - X2n+1+X2n+2+...+X3n<=k 其次0<=Xi<=1 并且我们要最大化∑3ni=1Ci?Xi 观察如上式子,显然为标准型线性规划. 单纯性出解即OK. 代码: #include <cstdio> #include <cstring> #include &l

BZOJ 3551 ONTAK2010 Peaks加强版 Kruskal重构树+可持久化线段树

题目大意:同3545 强制在线 3545题解传送门:http://blog.csdn.net/popoqqq/article/details/40660953 强制在线没法排序 启发式合并也就用不了了 Kruskal重构树是个挺好玩的东西 可以拿来处理一些最小生成树的边权最值问题 这里我们Kruskal连边时并不直接连边 而是新建一个节点ext 将两个点所在子树都连到ext的儿子上 比如说样例的树就建成了这样 图中红色的是原图的边权,黑色的是原图上的点 这样生成的树有一些十分优美的性质: 1.二

bzoj 3545&amp;&amp;3551: [ONTAK2010]Peaks &amp;&amp;加强版 平衡树&amp;&amp;并查集合并树&amp;&amp;主席树

3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 635  Solved: 177[Submit][Status] Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1. I

【BZOJ】【3550】【ONTAK2010】Vacation

网络流/费用流 Orz太神犇了这题…… 我一开始想成跟Intervals那题一样了……每个数a[i]相当于覆盖了(a[i]-n,a[i]+n)这个区间……但是这样是错的!!随便就找出反例了……我居然还一直当正解…… 实际上刚刚那个思路还有一个问题:题目中的长度为N的区间指的是给的原序列!而不是权值的区间!题就理解错了…… 看了下zyf的题解,才明白过来,要用跟志愿者招募一样的方法来做:另外,志愿者招募时每种志愿者是有无限多名的,但这题中每个数只能选一次,所以边权为a[i]的边的流量不能是INF,

bzoj 3545/3551: [ONTAK2010]Peaks -- 主席树,最小生成树,倍增

3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MB Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1. Input 第一行三个数N,M,Q.第二行N个数,第i个数为h_i接下来M行,每行

【BZOJ 3551】[ONTAK2010] Peaks加强版 Kruskal重构树+树上倍增+主席树

这题真刺激...... I.关于Kruskal重构树,我只能开门了,不过补充一下那玩意还是一棵满二叉树.(看一下内容之前请先进门坐一坐) II.原来只是用树上倍增求Lca,但其实树上倍增是一种方法,Lca只是他的一种应用,他可以搞各种树上问题,树上倍增一般都会用到f数组. |||.我们跑出来dfs序就能在他的上面进行主席树了. IV.别忘了离散. V.他可能不连通,我一开始想到了,但是我觉得出题人可能会是好(S)人(B),但是...... #include <cstdio> #include