zoukankan      html  css  js  c++  java
  • 题解-CF1239D Catowice City

    CF1239D Catowice City

    (n) 个人和 (n) 只猫。有 (m) 对人猫友谊,即第 (u_i) 个人认识第 (v_i) 只猫,保证第 (i) 个人和第 (i) 只猫认识。求 (j) 个人和 (p) 只猫使 (j+p=n(1le j,p<n)),并且这些人和猫互不认识。(t) 组测试数据。

    数据范围: (1le nle mle 10^6)(1le sum n,sum mle 10^6)


    首先这是个二分图,人一块,猫一块。

    将第 (i) 个人和第 (i) 只猫合并成一点,因为他们不能都选。

    (u_i)(v_i) 连一条有向边,表示如果第 (u_i) 点选人,(v_i) 点也必须选人

    如果出现环,则这些点要么全选人要么全选猫,不妨令选人。

    所以 ( exttt{Tarjan})强联通分量分出来。

    如果只有一个强联通分量,则必须全选人,与 ((1le j,p<n)) 不符,输出 ( exttt{No})

    否则选出拓扑序最后的强联通分量全选人,其他全选猫

    ( exttt{Tarjan}) 有个性质:编号为 (1) 的强联通分量拓扑序最后。

    时间复杂度 (Theta(n+m)),空间复杂度 (Theta(n+m))


    • 代码:
    #include <bits/stdc++.h>
    using namespace std;
    
    //Start
    typedef long long ll;
    typedef double db;
    #define mp(a,b) make_pair(a,b)
    #define x(a) a.first
    #define y(a) a.second
    #define b(a) a.begin()
    #define e(a) a.end()
    #define sz(a) int((a).size())
    #define pb(a) push_back(a)
    const int inf=0x3f3f3f3f;
    const ll INF=0x3f3f3f3f3f3f3f3f;
    
    //Data
    const int N=1e6;
    int n,m;
    vector<int> e[N+7];
    
    //Tarjan
    int ic,in[N+7],low[N+7],dfn[N+7],sc,st[N+7],cc,co[N+7],sm[N+7];
    void Tarjan(int u){
    	low[u]=dfn[u]=++ic,in[u]=1,st[++sc]=u;
    	for(int v:e[u])
    		if(!dfn[v]) Tarjan(v),low[u]=min(low[u],low[v]);
    		else if(in[v]) low[u]=min(low[u],dfn[v]);
    	if(dfn[u]==low[u]) for(int v=0,t=++cc;v!=u;) v=st[sc--],co[v]=t,in[v]=0,sm[t]++;
    }
    
    //KonnyWen
    void KonnyWen(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++) e[i].clear();
    	for(int i=1;i<=m;i++){
    		int u,v; scanf("%d%d",&u,&v);
    		if(u!=v) e[u].pb(v);
    	}
    	fill(dfn+1,dfn+n+1,0),fill(sm+1,sm+n+1,0),ic=sc=cc=0;
    	for(int i=1;i<=n;i++)if(!dfn[i]) Tarjan(i);
    	if(cc==1) return void(puts("No"));
    	printf("Yes
    %d %d
    ",sm[1],n-sm[1]);
    	for(int i=1;i<=n;i++)if(co[i]==1) printf("%d ",i); puts("");
    	for(int i=1;i<=n;i++)if(co[i]!=1) printf("%d ",i); puts("");
    }
    
    //Main
    int main(){
    	int t; scanf("%d",&t);
    	for(int ti=1;ti<=t;ti++) KonnyWen();
    	return 0;
    }
    

    祝大家学习愉快!

  • 相关阅读:
    C# 动态加载控件 (转)
    SQL 周月时间段
    js调用xml数据显示div层上下滚动的公告
    使用半透明的DIV实现禁用页面功能(转)
    学习jQuery第一天"Hello!How are you!"
    HTML生成类
    从无限畅想转来的
    SQL递归查询子类型
    js 图片缩显
    2020年统计用区划代码和城乡划分代码:安徽省乡镇编码
  • 原文地址:https://www.cnblogs.com/Wendigo/p/12916838.html
Copyright © 2011-2022 走看看