拓扑排序杂题
拓扑排序杂题
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;
}