王国连接
对于查尔斯国王而言,这是一个繁荣的一年,他正在迅速扩展他的王国。最近建造了一个美丽的新王国,在这个王国,有许多城市通过一些单行道相连。两个城市可能是由多条道路直接连接,这是为了确保高连通性。
在这个新的王国中,查尔斯国王在他的金融之都建立了一个城市,一个作为战争资本,他希望这两个首都之间有很高的连通性。一对城市的连通性表明城市A和城市B被定义为从城市A到城市B的不同路径的数量。如果可能,路径可以多次使用道路。如果它们不使用完全相同的道路序列,则认为两条路径是不同的。
在新王国和M单行道上有N个城市编号为1到N.城市1是货币资本,城市N是战争资本。
你是新王国最好的程序员之一,需要回答金融资本和战争资本的连通性,即从城市1到城市N的不同路径的数量。
输入描述:
第一行包含两个整数N和M.
然后跟随M行,每行有两个整数,分别表示x和y,1 <= x,y <= N,表示从城市x到城市y的道路。
输出描述:
打印从城市1到城市的不同路径的数量N模数1,000,000,000(10 ^ 9)。如果有无数多条不同的路径打印“INFINITE PATHS”(引号是为了清晰起见)。
示例输入:
5 5 1 2 2 4 2 3 3 4 4 5
示例输出:
2
示例输入:
5 5 1 2 4 2 2 3 3 4 4 5
示例输出:
INFINITE PATHS
约束:
2'; = N&LT; = 10,000(10 ^ 4)
1 <= M <= 1,00,000(10 ^ 5)
两个城市可能通过两条以上的道路相连,在这种情况下,这些道路在计算不同路径时会被视为不同
我用来解决问题的算法是:
如果没有周期,则使用重复计算所需的ans
我已将解决方案实施为:
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
vector<vector<pair<int, int> > > g;
int seen[10001] = {0};
int colour[10001] = {0};
bool has_cycle(int u) {
colour[u] = 1;
for(int i = 0; i < g[u].size(); i++) {
if(colour[g[u][i].first]==1) return true;
if(!colour[g[u][i].first])
if(has_cycle(g[u][i].first)) return true;
}
colour[u] = 2;
return false;
}
bool reachable(int u, int v) {
if(u==v) return true;
seen[u] = true;
for(int i = 0; i < g[u].size(); i++) {
if(!seen[g[u][i].first]) {
if(reachable(g[u][i].first, v)) return true;
}
}
return false;
}
long long mm[10001] = {0};
long long solve(int u, int n) {
if(u==n) return mm[u]=1;
if(mm[u]!=-2) return mm[u];
long long ans = 0;
for(int i = 0; i < g[u].size(); i++) {
ans += ((g[u][i].second%1000000000)*(solve(g[u][i].first, n)%1000000000)%1000000000);
ans %= 1000000000;
}
return mm[u]=ans;
}
long edge[100001];
int main() {
int n, m;
scanf("%d%d", &n, &m);
g.resize(n);
for(int i = 0; i < m; i++) {
int x, y;
scanf("%d%d", &x, &y);
x--; y--;
edge[i] = x*100000+y;
}
sort(edge, edge+m);
edge[m] = -1;
int last = edge[0];
int cnt = 1;
for(int i = 1; i <= m; i++) {
if(edge[i]!=last || i==m) {
int u, v;
u = last/100000;
v = last%100000;
if(i!=0) {
g[u].push_back(make_pair(v, cnt));
}
cnt = 1;
} else {
cnt++;
}
last = edge[i];
}
for(int i = 0; i < n; i++) mm[i] = -2;
if(reachable(0, n-1)) {
if(has_cycle(0)) printf("INFINITE PATHS\n");
else
printf("%lld\n", solve(0, n-1)%1000000000);
} else printf("0\n");
}
我无法通过此算法检测到问题
答案 0 :(得分:4)
数字(3)+(4)错误:
如果可达,则查找图中是否有任何循环 从节点0开始执行dfs。
如果有循环,则打印INFINITE PATHS
图中可能有一个循环,但如果目标无法从循环中到达,则所需的#path仍然是有限数。
示例:寻找从A到C的#paths
A-->D<-->B
|
----->C
在此处:G=(V,E)
,V = {A,B,C,D}
和E = {(D,B),(B,D),(A,C),(A,D)}
虽然可以从A
(A-> D-> B-> D)到达一个周期,但只有一条从A
到C
的路径。< / p>
要查找从源到目标的路径中是否存在周期,可以创建新图G'=(V',E')
,其中V'= { v | there is a path in the original graph from v to target }
和E' = V' x V' [intersection] E
(E
仅减少到V'
)的顶点,并在G'
上运行DFS / BFS。
另请注意,如果G'
中没有周期 - 根据定义它是DAG,那么从现在开始处理G'
,可能会简化查找#paths 。 (您还必须修剪无法从源访问的顶点,以确保它确实是DAG)。
答案 1 :(得分:2)
明显的错误。假设有一个循环,但是没有从循环到第二个城市的路径。然后你会说有无限数量的路径,但路径的数量实际上可能是有限的。
答案 2 :(得分:0)
您可以参考我的代码
#include <iostream>
#include <vector>
#include <set>
#include <stack>
#include <map>
#include <algorithm>
#include <iomanip>
#include <numeric>
#include "string.h"
#define MODE 1000000000
using namespace std;
int main () {
vector<int> adj[10001], inv_adj[10001];
int indegree[10001];
int visited[10001];
int ranks[10001];
long long total[10001];
int N, M;
cin >> N >> M;
memset(indegree, 0, (N+1)*sizeof(int));
adj[0].push_back(1);
inv_adj[1].push_back(0);
indegree[1] = 1;
for (int i=0;i<M;i++)
{
int s, t;
cin >> s >> t;
adj[s].push_back(t);
inv_adj[t].push_back(s);
indegree[t]++;
}
stack<int> st;
st.push(0);
memset(visited, 0, (N+1)*sizeof(int));
visited[0] = 1;
while (!st.empty()) {
int v = st.top();
st.pop();
for (int i=0;i<adj[v].size();i++)
if (!visited[adj[v][i]])
{
st.push(adj[v][i]);
visited[adj[v][i]] = 1;
}
}
if(!visited[N])
{
cout << 0 << endl;
return 0;
}
for (int i=1;i<=N;i++)
{
if(!visited[i]){
for (int j=0;j<adj[i].size();j++)
indegree[adj[i][j]]--;
}
}
int count = 0;
stack<int> topo;
for (int i=0;i<=N;i++)
{
int j;
for (j=0;j<=N;j++)
if (visited[j] && indegree[j] ==0)
break;
if (j > N)
{
cout << "INFINITE PATHS" << endl;
return 0;
}
else
{
topo.push(j);
ranks[count++] = j;
if (j == N)
break;
indegree[j] = -1;
for (int k=0;k<adj[j].size();k++)
indegree[adj[j][k]]--;
}
}
memset(total, 0, (N+1)*sizeof(long long));
total[N] = 1;
for (int i=count - 1;i>=0;i--)
{
int r = ranks[i];
for (int j=0;j<inv_adj[r].size();j++)
if(visited[inv_adj[r][j]])
{
total[inv_adj[r][j]] = (total[inv_adj[r][j]] + total[r]) % MODE;
}
}
cout << total[0] << endl;
return 0;
}