题解 P4645 【[COCI2006-2007 Contest#3] BICIKLI】

这个人怎么一天水四篇题解
%%%chen_zhe女装大佬

如果这题没有环的话只能算是一个简单dp题,然而有了环就会出现一些非常诡异并且棘手的情况。

首先看一下这组数据,由可爱的机房友人提供。

5 5
1 4
4 2
3 5
5 3
3 4

要画出来的话,大概是这个样子:

卧槽这是什么垃圾东西

总之就是,由1出发,4的入度-1,然而4的入度仍不为零,无法进行进一步的运算了。要说有环还的确是有环,不过这个环不仅没用还让我们的(dp_2)的值变成了0。

这样的毒瘤东西绝对不能要啊,但是怎么样的点才是像这样没用的点呢?我们发现,环里面的点可以到达2,但是从1根本就进不去这个环啊。

那么我们分别以1和2为起点进行一次正dfs和一次逆dfs标记能够从1能够到达的点和能够到达2的点。

必须两个都能到达才是有用的点,否则就要把这个点删掉。

然后删完就能快乐dp了。首先到达1的方法数肯定是1,然后对于每个没有前驱的点,将它的后继的方法数加上该点的方法数,删除该点和与该点相连的边。就是拓扑排序。

参考代码和其他补充如下:

#include<bits/stdc++.h>
using namespace std;
int n,m,u,v,in[10005];
long long dp[10005];
bool mk[10005][2],flag;
vector<int>dis[10005],des[10005];
queue<int>que;
void ring0(int p){
    mk[p][0]=1;
    for(int i=0;i<dis[p].size();i++)
        if(!mk[dis[p][i]][0])
            ring0(dis[p][i]);
}//标记以1为起点能够达到的点
void ring1(int p){
    mk[p][1]=1;
    for(int i=0;i<des[p].size();i++)
        if(!mk[des[p][i]][1])
            ring1(des[p][i]);
}//标记能够达到2的点
int main(){
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        cin>>u>>v;
        dis[u].push_back(v);
        des[v].push_back(u);
        in[v]++;
    }
    dp[1]=1;
    ring0(1);
    ring1(2);
    for(int i=1;i<=n;i++)
        if(!mk[i][1]||!mk[i][0])
            for(int j=0;j<dis[i].size();j++)
                in[dis[i][j]]--;//删除无用点
    for(int i=1;i<=n;i++)
        if(in[i]==0&&mk[i][0]&&mk[i][1])
            que.push(i);//拓扑排序初始化
    int top;
    while(!que.empty()){
        top=que.front();
        que.pop();
        for(int i=0;i<dis[top].size();i++){
            if(in[dis[top][i]]&&mk[dis[top][i]][0]&&mk[dis[top][i]][1]){
                dp[dis[top][i]]+=dp[top];//dp刷表转移
                dp[dis[top][i]]%=1000000000;
                in[dis[top][i]]--;
                if(in[dis[top][i]]==0)
                    que.push(dis[top][i]);//拓扑排序过程。
            }
        }
    }
    for(int i=1;i<=n;i++)
        if(in[i]&&mk[i][0]&&mk[i][1]){
            cout<<"inf";
            return 0;
        }//如果有用的点的入度还不为0,那么在1到2的路径上存在环,输出inf
    cout<<dp[2];
}

I'm Schwarzkopf Henkal.

原文地址:https://www.cnblogs.com/Schwarzkopf-Henkal/p/11775576.html