qduoj - 小Z的集训队考验(拓扑排序+动态规划)
生活随笔
收集整理的這篇文章主要介紹了
qduoj - 小Z的集训队考验(拓扑排序+动态规划)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接:點擊查看
題目大意:給出一個有向圖,問拓撲排序共有多少種方案,需要注意以下幾點:
題目分析:問到了方案數肯定是動態規劃,我們就要設計一下動態規劃該怎么寫,因為拓撲排序用到的是bfs,每次完整的排序都能得到一條單鏈,所以我們可以用樹形dp的思想來設計,我們令dp[i]代表終點為i時的方案數,這樣初始化時其他的點的dp全部是0,所有入度為0的點的dp全部為1,每次更新相鄰頂點入度時,順便轉移一下狀態即可,等訪問到了出度為0的點時,說明該點已經是終點了,結果加上該點的dp值即可,注意對單點特判一下,因為單點的dp值肯定是1,所以我們在main函數中找出一共有多少個單點,然后讓結果減去單點的數量就可以了,題目保證了答案在int范圍內,所以題目也沒有其他的坑點了
代碼,更多的看注釋吧:
#include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cstring> #include<algorithm> #include<stack> #include<queue> #include<map> #include<sstream> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e5+100;int n,m;int ans;int in[N];//入度 int dp[N];vector<int>node[N];void topo() {memset(dp,0,sizeof(dp));queue<int>q;for(int i=1;i<=n;i++)if(in[i]==0){dp[i]=1;q.push(i);}while(!q.empty()){int cur=q.front();q.pop();if(node[cur].empty())ans+=dp[cur];for(int i=0;i<node[cur].size();i++){int next=node[cur][i];in[next]--;dp[next]+=dp[cur];if(in[next]==0) q.push(next);}} }int main() { // freopen("input.txt","r",stdin);while(scanf("%d%d",&n,&m)!=EOF){memset(in,0,sizeof(in));ans=0;for(int i=1;i<=n;i++)node[i].clear();while(m--){int u,v;scanf("%d%d",&u,&v);node[u].push_back(v);in[v]++;}for(int i=1;i<=n;i++)//處理一下單點:入度=出度=0 if(in[i]==0&&node[i].empty())ans--;topo();printf("%d\n",ans);}return 0; }?
總結
以上是生活随笔為你收集整理的qduoj - 小Z的集训队考验(拓扑排序+动态规划)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: POJ - 2449 Remmargut
- 下一篇: HDU - 1547 Bubble Sh