發表文章

目前顯示的是有「拓樸排序」標籤的文章

[Codeforces] 731D. 80-th Level Archeology

題目連結: http://codeforces.com/problemset/problem/731/D 我覺得我的作法感覺不太對(?但還是講一下好了 我的做法是先把大小關係建成一張DAG,而這樣的話會發現題目變成說可不可以找到一種拓樸排序方法使得序列會是循環的字串,而又已經知道循環其實就只有可能中間斷開一個而已,所以我們不妨找到中間斷開的那個關係,並追本朔源到最前面的那個,從他開始拓樸排序,看會不會是好的。 #include <bits/stdc++.h> using namespace std; #define PB push_back #define FF first #define SS second const int N = 500000 + 5; const int C = 1000000 + 5; class DJS{ private: vector<int> arr; public: inline void init(int n){ arr.resize(n); for(int i=0;i<n;i++) arr[i]=i; } int query(int x){ if(arr[x]!=x) arr[x] = query(arr[x]); return arr[x]; } void merge(int a, int b){ int u = query(a), v = query(b); arr[max(u, v)]=min(u, v); } } djs; vector<int> G[C], cur; int in[C]; inline void kill(){cout<<"-1\n...

[TIOJ] 1589. 蚯蚓之入侵雅勒問題 Athena

題目連結: http://tioj.infor.org/problems/1589 很明顯的可以知道到一個點的方法數,就是到所有連到他的人的方法數加起來,所以我們可以用類似DP的方法記錄從起點到每個點的方法數,而DP順序就按照拓樸排序就好了XD #include <bits/stdc++.h> using namespace std; #define PB push_back typedef long long lld; const int N = 250 + 5; vector<int> G[N]; lld way[N]; int in[N]; int main(){ ios_base::sync_with_stdio(0);cin.tie(0); int vv, ee, m; cin>>vv>>ee>>m; for(int i=0;i<ee;i++){ int u, v; cin>>u>>v; G[u].PB(v); in[v]++; } int st, ed; cin>>st>>ed; way[st]=1; queue<int> qq; for(int i=0;i<vv;i++) if(in[i]==0) qq.push(i); while(!qq.empty()){ int u = qq.front(); qq.pop(); for(auto v: G[u]){ way[v] = (way[v]+way[u])%m; in[v]--; if(in[v]==0) qq.push(v); } } cout<...

[Codeforces] 721C. Journey

題目連結: http://codeforces.com/problemset/problem/721/C 莫名其妙吃了MLE,只好把int改short, long long改int = = 本題的做法滿DP的,我狀態直接訂成$dp[i][j]$代表起點到$i$號節點,經過$j$個中繼點所需的最短時間,而DP的順序就按照圖的拓樸排序順序DP就可以好好DP了,不過要注意的是起點有可能不會是拓樸排序的第一個點,所以要稍微判一下... #include <cstdio> #include <vector> #include <utility> #include <stack> #include <queue> using namespace std; typedef long long lld; #define PB push_back typedef pair<short,int> PSI; typedef pair<short,short> PSS; #define FF first #define SS second const int N = 5000 + 5; const int INF = 1<<30; short in[N]; int dp[N][N]; PSS ori[N][N]; vector<PSI> G[N]; int main(){ short n, m;int t; scanf("%hd%hd%d",&n,&m,&t); fill(dp[0], dp[n]+n+1, INF); for(int i=0;i<m;i++){ short u, v; int c; scanf("%hd%hd%d",&u,&v,&c); G[u].PB({v, c}); in[v]++; ...

[TIOJ] 1226. H遊戲

題目連結: http://tioj.infor.org/problems/1226 我原本以為本題就裸裸的邊作拓樸排序邊算每個點所會花到的時間就好,後來一直WA後才發現原來那樣做是錯的,因為一個點可以被走過很多次,所以有些邊要再乘以路徑數,所以還要多紀錄一下路徑數再好好算才對。 #include <bits/stdc++.h> using namespace std; #define PB push_back typedef pair<int,int> PII; #define FF first #define SS second const int mod = 32768; const int V = 1005; int inDg[V], ans[V], cnt[V]; vector<PII> g[V]; vector<string> names; bitset<V> visited; void init(int); int main(){ ios_base::sync_with_stdio(0);cin.tie(0); int t;cin>>t; for(int _=1;_<=t;_++){ cout<<"Game #"<<_<<'\n'; int n, v, e;cin>>n>>v>>e; init(v); for(int i=0;i<n;i++){ string ss;cin>>ss; names.PB(ss); } for(int i=0;i<e;i++){ int st, ed, w;cin>>st>>ed>...