拓扑排序杂题

拓扑排序杂题

P1113 杂务

裸题 注意读入时\(0\)的巧妙判断

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define fa(x) t[x].fa
#define ls(x) t[x].son[0]
#define rs(x) t[x].son[1]
const int N = 1e5 + 5;
char buf[1<<24] , *p1 , *p2;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
//#define getchar() cin.get();
int read()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f ;
}

int n , m , tot , rd[N] , f[N] , ans , a[N];
int q[N] , head = 1 , tail = 0;

vector<int> e[N];
inl void add ( int u , int v ) { e[u].emplace_back(v); }

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr) , cout.tie(nullptr);
	n = read();
	for ( int i = 1 , id , temp ; i <= n ; i ++ )
	{
		read() , f[i] = a[i] = read();
		while ( temp = read() ) rd[i] ++ , add ( temp , i );
	}
	for ( int i = 1 ; i <= n ; i ++ ) if ( !rd[i] ) q[++tail] = i;
	while ( head <= tail )
	{
		int u = q[head++];
		for ( auto v : e[u] )
		{
			f[v] = max ( f[v] , f[u] + a[v] );
			if ( --rd[v] == 0 ) q[++tail] = v;
		}
	}
	for ( int i = 1 ; i <= n ; i ++ ) ans = max ( ans , f[i] );
	cout << ans << endl;
	return 0;
}

P4017 最大食物链计数

一道很好的思维题

题意可以转化为最垃圾的东西到最牛逼的东西有多少条路

我们设置\(f[i]\)为以\(i\)结尾的食物链的条数 那么\(f[i]=\sum f[pre]\)(模意义下)

那么最终答案就是\(\sum f[k](eat[k]=0)\)

拓扑排序\(dp\)即可 注意初始化垃圾节点为\(1\)

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
const int N = 1e5 + 5;
const int mod = 80112002; 
char buf[1<<24] , *p1 , *p2;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
//#define getchar() cin.get();
int read()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f ;
}

int n , m , f[N] , rd[N] , eat[N] , ans;//f[i]表示以i节点为结尾的食物链条数
int q[N] , head = 1 , tail = 0;

vector<int> e[N];
inl void add ( int u , int v ) { e[u].emplace_back(v); }

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr) , cout.tie(nullptr);
	n = read() , m = read();
	for ( int i = 1 , u , v ; i <= m ; i ++ ) u = read() , v = read() , add ( u , v ) , rd[v] ++ , eat[u] ++;
	for ( int i = 1 ; i <= n ; i ++ ) if ( !rd[i] ) q[++tail] = i , f[i] = 1;
	while ( head <= tail )
	{
		int u = q[head++];
		for ( auto v : e[u] )
		{
			f[v] = ( f[v] + f[u] ) % mod;
			if ( --rd[v] == 0 ) q[++tail] = v; 
		}
	}
	for ( int i = 1 ; i <= n ; i ++ ) if ( !eat[i] ) ans = ( ans + f[i] ) % mod;
	cout << ans << endl;
	return 0;
}

P1347 排序

拓扑排序 判环就是看有没有没访问到的点 无法判断的情况就是同一层节点有两个及以上出度为\(0\) 那么就无法判断这两个节点的大小关系

细节较多 如果判断出来无解或者有解也需要输入完 输入边的时候不要忘了统计入度

判断有环的情况就是有点的入度没访问完 所以出现了环

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
const int N = 1e5 + 5;
//char buf[1<<24] , *p1 , *p2;
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
#define getchar() cin.get();
int read()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f ;
}

int n , m , f[N] , rd[N] , tmp[N] , res , loc;
int q[N] , head = 1 , tail = 0;

vector<int> e[N] , ans;
void add ( int u , int v ) { e[u].emplace_back(v); }

int tp ()
{
	ans.clear();
	head = 1 , tail = 0;
	int ru0 = 0 , ret = 1;
	for ( int i = 1 ; i <= n ; i ++ )
	{
		tmp[i] = rd[i];
		if ( !tmp[i] ) q[++tail] = i , ru0 ++;
	}
	if ( ru0 > 1 ) ret = 0;
	while ( head <= tail )
	{
		int u = q[head++];
		ru0 = 0 , ans.emplace_back(u);
		for ( auto v : e[u] )
			if ( --tmp[v] == 0 ) q[++tail] = v , ru0 ++;
		if ( ru0 > 1 ) ret = 0;
	}
	for ( int i = 1 ; i <= n ; i ++ ) if ( tmp[i] > 0 ) ret = -1;
	return ret;
}

string s;
signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr) , cout.tie(nullptr);
	n = read() , m = read();
	for ( int i = 1 ; i <= m ; i ++ ) 
	{
		cin >> s;
		int x = s[0] - 64 , y = s[2] - 64;
		add ( x , y ) , rd[y] ++;
		if ( res == 0 ) res = tp() , loc = i;
		
	}
	if ( res == 0 ) cout << "Sorted sequence cannot be determined.";
	else if ( res == 1 )
	{
		cout << "Sorted sequence determined after " << loc << " relations: ";
		for ( auto v : ans ) cout << (char)(v+64);
		cout << '.' << endl;
	}
	else cout << "Inconsistency found after " << loc << " relations.";
	return 0;
}

P1038 [NOIP2003 提高组] 神经网络

直接模拟即可 非输入层可以先整体减掉阈值\(u\)

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define pii pair<int,int>
#define inl inline
const int N = 1e5 + 5;
char buf[1<<24] , *p1 , *p2;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
//#define getchar() cin.get();
int read()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f ;
}

int n , m , cd[N] , rd[N] , c[N] , u[N];
int q[N] , head = 1 , tail = 0;

vector<pii> e[N];
inl void add ( int u , int v , int w ) { e[u].emplace_back(v,w); }
signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr) , cout.tie(nullptr);
	n = read() , m = read();
	for ( int i = 1 ; i <= n ; i ++ ) c[i] = read() , u[i] = read();
	for ( int i = 1 , u , v , w ; i <= m ; i ++ ) u = read() , v = read() , w = read() , add ( u , v , w ) , rd[v] ++ , cd[u] ++;
	for ( int i = 1 ; i <= n ; i ++ ) if ( rd[i] ) c[i] = -u[i];
	for ( int i = 1 ; i <= n ; i ++ ) if ( !rd[i] && c[i] > 0 ) q[++tail] = i; 
	while ( head <= tail )
	{
		int u = q[head++];
		for ( auto [v,w] : e[u] )
		{
			c[v] += c[u] * w;
			if ( !--rd[v] && c[v] > 0 ) q[++tail] = v; 
		}
	}
	int flag = 1;
	for ( int i = 1 ; i <= n ; i ++ ) if ( !cd[i] && c[i] > 0 ) cout << i << ' ' << c[i] << endl , flag = 0; 
	if ( flag ) cout << "NULL" << endl;
	return 0;
}

P1983 [NOIP2013 普及组] 车站分级

对于每一条路径 将所有未经过的小点向停靠的大点连边 然后拓扑排序跑一下最长链即可

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define pii pair<int,int>
#define inl inline
const int N = 1e3 + 5;
//char buf[1<<24] , *p1 , *p2;
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
#define getchar() cin.get();
int read()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f ;
}

int n , m , rd[N] , vis[N] , s[N][N] , cnt[N] , mp[N][N] , f[N] , maxx;
int q[N] , head = 1 , tail = 0;

vector<int> e[N];
inl void add ( int u , int v ) { e[u].emplace_back(v); }

void tp () 
{
	for ( int i = 1 ; i <= n ; i ++ ) if ( !rd[i] ) q[++tail] = i , f[i] = 1;
	while ( head <= tail ) 
	{
		int u = q[head++];
		for ( auto v : e[u] )
		{
			f[v] = max ( f[u] + 1 , f[v] );
			if ( !--rd[v] ) q[++tail] = v;
		}
	}
}

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr) , cout.tie(nullptr);
	n = read() , m = read();
	for ( int i = 1 ; i <= m ; i ++ )
	{
		cnt[i] = read();
		memset ( vis , 0 , sizeof vis );
		for ( int j = 1 ; j <= cnt[i] ; j ++ ) s[i][j] = read() , vis[s[i][j]] = 1;
		for ( int j = s[i][1] ; j <= s[i][cnt[i]] ; j ++ )
		{
			if ( vis[j] ) continue;
			for ( int k = 1 ; k <= cnt[i] ; k ++ )
				if ( !mp[j][s[i][k]] ) add ( j , s[i][k] ) , rd[s[i][k]] ++ , mp[j][s[i][k]] = 1;
		}
	}
	tp();
	for ( int i = 1 ; i <= n ; i ++ ) maxx = max ( maxx , f[i] );
	cout << maxx << endl;
	return 0;
}
posted @ 2023-08-06 11:27  Echo_Long  阅读(8)  评论(0编辑  收藏  举报