codeforces C. Customs Controls 2
C. Customs Controls 2
time limit per test2 seconds
memory limit per test512 megabytes
Look how short the statement is! This must be the easiest problem.
Given a directed acyclic graph 𝐺, you need to assign each vertex 𝑖 a positive integer weight 𝑤𝑖. Your goal is to make all paths from 1 to 𝑛 of equal length.
A directed acyclic graph is a graph with directed edges and without cycles.
The length of a path is defined as the sum of the weights of vertices on the path.
Input
The first line contains a positive integer 𝑇 (1≤𝑇≤104), denoting the number of test cases.
For each testcase:
The first line contains two integers 𝑛,𝑚 (1≤𝑛≤2⋅105, 1≤𝑚≤5⋅105), denoting the number of vertices and edges.
The next 𝑚 lines each contains two integers 𝑢, 𝑣, denoting an edge from 𝑢 to 𝑣.
It is guaranteed that ∑𝑛≤2⋅105, ∑𝑚≤5⋅105.
It is guaranteed that the graph contains no multiple edges, no self-loops and no cycles. It is also guaranteed that every vertex is reachable from 1 and can reach 𝑛.
Output
For each testcase, if there is no solution, then output "No" on a single line. Otherwise, output "Yes" on the first line, then 𝑛 positive integers 𝑤1,𝑤2,…,𝑤𝑛 (1≤𝑤𝑖≤109) on the second line.
本题要求判断能否通过对点赋权值来实现使从起点1到n点的所有路径的长度和一致
题目告知我们这是一个无环的有向图,并且本题的核心判断是能不能构造每条路径的路径和都一致的图。
根据:如果图中有某个点 i,其在某条路径上让这条路径比其他路径长或短,那就不能统一所有路径的长度。
所以可以通过从 1 到 i 的最短路径 和 从 i 到 n 的最长路径 构造出一条从 1 到 n 的完整路径来判断是否能够构造。
点击查看代码
int dp[MAXN], rdp[MAXN]; //1到i最短路径,i到n最长路径
int valid = 1;
int target = dp[n];
for (int i = 1; i <= n; i++) {
if(dp[i] + rdp[i] - 1 != target){ //减 1 是因为 i 被重复计算
valid = 0;
break;
}
}
因为这是一个无环有向图,我们通过正向和反向两次拓扑排序来获取dp[i]和rdp[i],考虑到内存与问题处理,选择bfs的拓扑也就是kahn算法
点击查看代码
//正向拓扑
void topo_f(){
int front = 0, rear = 0;
queue[rear++] = 1;
dp[1] = 1; //因为是点上的权值所以起点要算
while(front < rear){
int u = queue[front++];
for(int i = head[u]; i; i = edges[i].next){
int v = edges[i].to;
if(dp[v] > dp[u] + 1){ //尝试用u更新v的最短路径长度
dp[v] = dp[u] + 1;
}
if (--indeg[v] == 0){ //前驱为0时可以入对
queue[rear++] = v;
}
}
}
}
//反向拓扑
void topo_b(){
int front = 0, rear = 0;
queue[rear++] = n; //从最后开始BFS
rdp[n] = 1;
while(front < rear){
int u = queue[front++];
for(int i = rh[u]; i; i = redges[i].next){
int v = redges[i].to;
if(rdp[v] < rdp[u] + 1){ //更新v的最长路径长度
rdp[v] = rdp[u] + 1;
}
if(--outdeg[v] == 0){
queue[rear++] = v;
}
}
}
}
完整代码
点击查看代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXN 500005
struct Edge{
int to,next;
};
struct Edge edges[MAXN],redges[MAXN];;
int n, m;
int head[MAXN], rh[MAXN]; //正向和反向的邻接表表头
int tot, rtot; //正向边总数与反向边总数
int indeg[MAXN], outdeg[MAXN]; //正向图中i的入度,反向图中i的出度
int dp[MAXN], rdp[MAXN]; //1到i最短,i到n最长
int queue[MAXN];
//初始化图结构与路径状态
void init(int n){
tot = rtot = 0;
for(int i = 1; i <= n; i++){
head[i] = rh[i] = 0;
indeg[i] = outdeg[i] = 0;
dp[i] = 1e9;
rdp[i] = 0;
}
}
void add_edge(int u, int v){
edges[++tot].to = v;
edges[tot].next = head[u];
head[u] = tot;
indeg[v]++; //每次插入边后节点v的入度加1
redges[++rtot].to = u;
redges[rtot].next = rh[v];
rh[v] = rtot;
outdeg[u]++; //每次插入边后节点u的出度加1
}
//正向拓扑
void topo_f(){
int front = 0, rear = 0;
queue[rear++] = 1;
dp[1] = 1; //因为是点上的权值所以起点要算
while(front < rear){
int u = queue[front++];
for(int i = head[u]; i; i = edges[i].next){
int v = edges[i].to;
if(dp[v] > dp[u] + 1){ //尝试用u更新v的最短路径长度
dp[v] = dp[u] + 1;
}
if (--indeg[v] == 0){ //前驱为0时可以入对
queue[rear++] = v;
}
}
}
}
//反向拓扑
void topo_b(){
int front = 0, rear = 0;
queue[rear++] = n; //从最后开始BFS
rdp[n] = 1;
while(front < rear){
int u = queue[front++];
for(int i = rh[u]; i; i = redges[i].next){
int v = redges[i].to;
if(rdp[v] < rdp[u] + 1){ //更新v的最长路径长度
rdp[v] = rdp[u] + 1;
}
if(--outdeg[v] == 0){
queue[rear++] = v;
}
}
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n, &m);
init(n);
for(int i = 0; i < m; i++){
int u, v;
scanf("%d%d", &u, &v);
add_edge(u, v); //有向图
}
topo_f();
topo_b();
int valid = 1;
int target = dp[n];
for (int i = 1; i <= n; i++) {
if(dp[i] + rdp[i] - 1 != target){ //检查能否使得每条路径的路径和一致
valid = 0;
break;
}
}
if(!valid){
printf("No");
}else{
printf("Yes");
for(int i = 1; i <= n; i++){
printf("1%c", i == n ? '\n' : ' ');
}
}
}
return 0;
}

浙公网安备 33010602011771号