首页 > 其他分享 >Tarjan 例题:洛谷P1407 [国家集训队] 稳定婚姻

Tarjan 例题:洛谷P1407 [国家集训队] 稳定婚姻

时间:2023-08-11 13:22:46浏览次数:51  
标签:boy Tarjan 洛谷 cur int 题解 编号 girl 例题

在洛谷中查看


题意:

自己读一下,大致就是 \(2n\) 个点,每个点编号为 \(1 - 2n\),\(\lfloor 编号/2 \rfloor\) 相同的点连条边。
然后再给 \(m\) 条边。
问:将每个 \(\lfloor 编号/2 \rfloor\) 相同的点间连的边断开,还能不能使每个 编号为奇数的点 都有一个 编号为偶数的点 对应。

这个不太好讲,你们自己看看题呗 q(≧▽≦q)。

思路:

一篇题解讲得挺好的,我就给你们讲下为什么吧。

大致的思考路线就是:

  1. 第 \(i\) 对婚姻不安全,就说明:\(B_i\) 和 \(G_i\) 在同一个强连通分量里。
    证明:每条边连的两个点一定一男一女嘛(一奇一偶)。那么如果构成了环,那环上的点数一定是偶数,所以每个人都能找到其他配偶。

  2. 那就只用看能不能构成环了嘛,考虑用 Tarjan 求。
    PS:评论区有 dalao 说用点双联通,但我还不会,只能讲讲我会的。以后学了再来试试吧。
    如果这第 \(i\) 对夫妻在同一个强连通分量里,则是不安全的婚姻。所以缩个点就行,但问题来了,不能在无向图缩啊(所以有 dalao 说用点双)。
    那我们需要将它转换成有向图。


dalao 的题解里说了。

  • 夫妻之间:\(girl\) → \(boy\)
  • 情人之间:\(boy\) → \(girl\)

但为什么呢,其实很好想,自己画个图就知道了。
如果都 \(girl\) → \(boy\) 或 \(boy\) → \(girl\),那某些点出度就为 \(0\) 了,找不了其他恋人了。


Code:

(这次没什么注释,我觉得挺好理解的,如果你没懂,直接喊我,或 QQ 问,我会解答的,题解就是为了讲明白,谢谢~)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 8e3+5;
int n,m,dfn[N],low[N],num,cnt,col[N],st[N],top;
string boy,girl; 
vector<int> g[N],color[N];
map<string,int> cur;
inline int read(){
	int s=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){s=(s<<1)+(s<<3)+(c^48);c=getchar();}
	return s*f;
}
void tarjan(int x){
	dfn[x]=low[x]=++num;st[++top]=x;
	for(int i=0;i<g[x].size();i++){
		int t=g[x][i];
		if(!dfn[t])tarjan(t),low[x]=min(low[x],low[t]);
		else if(!col[t])low[x]=min(low[x],dfn[t]);
	}
	if(dfn[x]==low[x])for(cnt++;st[top+1]!=x;top--)col[st[top]]=cnt,color[cnt].push_back(st[top]);
}
int main(){
	/*
	solution:
		对于n对夫妻,我们将男的连向 
	*/
	n=read();
	for(int i=1;i<=n;i++){
		cin>>girl>>boy;
		cur[girl]=i*2-1;cur[boy]=i*2;
		g[cur[girl]].push_back(cur[boy]);
	}
	m=read();
	for(int i=1;i<=m;i++){
		cin>>girl>>boy;
		g[cur[boy]].push_back(cur[girl]);//不同于上面,连的方向相反 
	}
	for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
	for(int i=1;i<=n;i++){
		if(col[i*2-1]==col[i*2])cout<<"Unsafe\n";
		else cout<<"Safe\n";
	} 
	return 0;
}

标签:boy,Tarjan,洛谷,cur,int,题解,编号,girl,例题
From: https://www.cnblogs.com/JT-dw/p/JT-NO_5.html

相关文章

  • 洛谷 P3387 【模板】缩点
    在洛谷中查看所有思考都在代码,可以结合代码思考谢谢~#include<bits/stdc++.h>usingnamespacestd;constintN=1e4+5;intn,m,val[N];intdfn[N],low[N],num,col[N],cnt;//col记录每个点属于哪个联通分量//num记录遍历时间cnt记录缩点完后有多少个点in......
  • Tarjan
    我写这个随笔是让我更加理解算法,防止以后出错,因为我今天调Tarjan调了3个多小时,后来还是在大佬的帮忙下调出来了,问题不少先来看错误的(40pts): //缩点//https://www.luogu.com.cn/problem/P3387#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;con......
  • 洛谷 CF572B题解
    思路首先,将SELL和BUY交易数据分别存放在两个桶。接下来,从小到大遍历。取出最小的\(s\)个:从大到小遍历,取出最大的\(s\)个。分别存放在queue和stack中,如果不到\(s\)就取完为止。最后,输出queue和stack中的所有元素即可。代码实现:#include<bits/stdc++.h>usi......
  • 递推算法例题C++
    1、移动路线【题目描述】X桌子上有一个m行n列的方格矩阵,将每个方格用坐标表示,行坐标从下到上依次递增,列坐标从左至右依次递增,左下角方格的坐标为(1,1),则右上角方格的坐标为(m,n)。小明是个调皮的孩子,一天他捉来一只蚂蚁,不小心把蚂蚁的右脚弄伤了,于是蚂蚁只能向上或向右移动。小明......
  • 洛谷 P1336 最佳课题选择 题解
    P1336最佳课题选择题解状态:考虑\(f_{i,j}\)表示前\(i\)种论文里面,一共写了\(j\)篇,的最少花费时间。转移策略:我们一次考虑每一种论文写多少篇。假设写\(k\)篇,\(k\in[0,j]\cap\mathbb{Z}\),有转移方程:\[f_{i,j}=min(f_{i-1,j-k}+cost(i,k)),k\in[0,j]\cap\mathbb{......
  • 洛谷 P6010 - [USACO20JAN] Falling Portals P
    先考虑怎么对一组询问求解答案。容易想到一种贪心策略:如果\(a_{q_i}<a_i\),那么我们肯定希望自己能够尽量快地下落,因此如果遇到一个下落速度大于当前世界下落速度的传送门我们肯定就会进那个世界,如此走下去知道能够传送到世界\(q_i\)为止。对于\(a_{q_i}>a_i\)的情况也类似,只......
  • 洛谷 P8500 - [NOI2022] 冒泡排序
    显然将权值离散化是没有问题的,因为必然存在一组最优解,满足每个\(a_i\)都取自于某个\(V_i\),于是不管三七二十一先将\(V_i\)离散化了再说。考虑从部分分入手逐步分析这道题:特殊性质A:\(V_i=1\)相当于这个区间中的数必须是\(1\),先将这些数去掉不管,紧接着考虑\(V_i=0\)的......
  • 【LGR-148-Div.3】洛谷基础赛 #1 & MGOI Round I
    【LGR-148-Div.3】洛谷基础赛#1&MGOIRoundIT1luoguP9502『MGOI』SimpleRoundI|A.魔法数字\(100pts\)水题,场切了。#include<bits/stdc++.h>usingnamespacestd;#definelllonglong#definesortstable_sort#defineendl'\n'intmain(){ ......
  • tarjan,点双和边双学习笔记。
    发现之前学的真的一塌糊涂呢(/ω\)很多非常精髓的地方理解的都不够好,比如说为啥我要用一棵dfs树来为框架,跑tarjan?这里我就理解的不好,所以我来重新写一篇,加深加深印象。以下一切默认为无向图。0.基本概念这里面说的非常不严谨,只是为了方便理解啦awa连通分量:你可以简单的......
  • 【LGR-148-Div.3】洛谷基础赛 #1 & MGOI Round I
    【LGR-148-Div.3】洛谷基础赛#1&MGOIRoundI据说是普及组难度?T1P9502『MGOI』SimpleRoundI|A.魔法数字\(100pts\)题目描述初级魔法士小M的魔法数字是\(2\)。给定一个正整数\(n\),小M需要找到最大的偶数\(m\),使得\(2^m<n\)。又双叒叕是个水题,然后被又双......