ybtoj 11.13 S组二分BFSD. 道路与航线
Posted SSL_ZZL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ybtoj 11.13 S组二分BFSD. 道路与航线相关的知识,希望对你有一定的参考价值。
ybtoj 11.13 S组 D. 道路与航线
题面
样例
样例输入1
4 6 1 4
2 3 0
1 2 1
3 4 1
4 3 0
2 1 1
1 3 1
样例输出1
3 5
样例2
去掉第一个c和第一个b。见选手附加文件。比完赛就没大数据了((((
解题思路
😅出题人良心,数据范围明明3*10^6,于是40分卡了一小时😅
方法一:二分答案,然后暴力bfs就好了
方法二:用vis[i]标记起点能不能到达 i
- 如果 s 能走到 i,i 能走到 j ,那么 s 也能走到 j
- 如果s 不能走到 i,i 能走到 j,但是不能保证后面加入边时 s 不能走到 i :将 i 和 j 连起来,下次连到 i 时,再做一个小bfs(i)
Code
方法一
#include <bits/stdc++.h>
#define N 3001000
using namespace std;
struct DT{
int to, next;
}a[N * 2];
int n, m, S, T, l, r, mid, ans;
int num, head[N], v[N], x[N], y[N], id[N];
queue<int> q;
void add(int x, int y) {
a[++ num] = (DT){ y, head[x] }, head[x] = num;
}
int check(int m) {
memset(head, 0, sizeof(head));
num = 0;
for(int i = 1; i <= m; i ++) {
add(x[i], y[i]);
if(!id[i]) add(y[i], x[i]);
}
memset(v, 0, sizeof(v));
while(!q.empty()) q.pop();
q.push(S);
while(!q.empty()) {
int x = q.front();
for(int i = head[x]; i; i = a[i].next) {
int y = a[i].to;
if(!v[y]) v[y] = 1, q.push(y);
if(y == T) return 1;
}
q.pop();
}
return 0;
}
int main() {
freopen("road.in", "r", stdin);
freopen("road.out", "w", stdout);
scanf("%d %d %d %d", &n, &m, &S, &T);
for(int i = 1; i <= m; i ++)
scanf("%d %d %d", &x[i], &y[i], &id[i]);
l = 1, r = m;
while(l <= r) {
mid = (l + r) / 2;
if(check(mid))
ans = mid, r = mid - 1;
else l = mid + 1;
}
printf("%d ", ans);
l = 1, r = m, swap(S, T);
while(l <= r) {
mid = (l + r) / 2;
if(check(mid))
ans = mid, r = mid - 1;
else l = mid + 1;
}
printf("%d", ans);
}
方法二
#include <bits/stdc++.h>
#define N 3001000
using namespace std;
struct DT{
int to, next;
}a[N * 2];
int n, m, S, T, v[N], w[N][3];
int num, head[N];
queue<int> q;
void add(int x, int y) {
a[++ num] = (DT){ y, head[x] }, head[x] = num;
}
int check(int x, int y, int T) {
if(!v[x]) add(x, y);
if(v[x] && !v[y]) {
v[y] = 1, q.push(y);
while(!q.empty()) {
int xx = q.front();
for(int i = head[xx]; i; i = a[i].next)
if(!v[a[i].to]) q.push(a[i].to), v[a[i].to] = 1;
q.pop();
}
}
return v[T];
}
int find(int x, int y) {
v[x] = 1;
for(int i = 1; i <= m; i ++) {
if(check(w[i][0], w[i][1], y)) return i;
if(w[i][2] == 0 && check(w[i][1], w[i][0], y))
return i;
}
return -1;
}
int read()
{
char c = getchar();
while(c<'0' || c>'9') c=getchar();
int t = 0;
while(c>='0' && c<='9')
{
t = t*10+c-'0';
c=getchar();
}
return t;
}
int main() {
freopen("road.in", "r", stdin);
freopen("road.out", "w", stdout);
n = read(), m = read(), S = read(), T = read();
for(int i = 1; i <= m; i ++)
w[i][0] = read(), w[i][1] = read(), w[i][2] = read();
printf("%d ", find(S, T));
memset(v, 0, sizeof(v));
memset(head, 0, sizeof(head));
num = 0;
printf("%d", find(T, S));
}
以上是关于ybtoj 11.13 S组二分BFSD. 道路与航线的主要内容,如果未能解决你的问题,请参考以下文章