SCU 4444 Travel
讨论:
如果
a
<
b
a<b
a<b
1 与 n 之间连的是
a
a
a 边,输出 a
1 与 n 之间连的是
b
b
b 边,对 b 做一个
0
/
1
0/1
0/1
b
f
s
bfs
bfs
如果
a
>
b
a>b
a>b
1 与 n 之间连的是
b
b
b 边,输出 b
1 与 n 之间连的是
a
a
a 边,对 a 做一个
0
/
1
0/1
0/1
b
f
s
bfs
bfs
问题就在于
b
b
b 边的数量太多,考虑到如果用一个点去更新其它点,每个点都做完后最多只会失配
m
m
m 次
所以我们用一个链表维护还没有被更新的点
如果当前失配了,那么总共最多
m
m
m 次
如果当前没有失配,那么会删一个点,最多
n
n
n 次
#include<bits/stdc++.h>
#define N 100050
#define M 1000050
using namespace std;
int read(){
int cnt = 0, f = 1; char ch = 0;
while(!isdigit(ch)){ ch = getchar(); if(ch == '-') f = -1;}
while(isdigit(ch)) cnt = cnt*10 + (ch-'0'), ch = getchar();
return cnt * f;
}
typedef long long ll;
int pre[N], suf[N];
int vis[N], out[N];
int first[N], nxt[M], to[M], tot;
void add(int x, int y){ nxt[++tot] = first[x]; first[x] = tot; to[tot] = y;}
int n, m, a, b;
ll dis[N];
const ll inf = 1e15;
void del(int x){ pre[suf[x]] = pre[x]; suf[pre[x]] = suf[x];}
void FSY(){
queue<int> q; q.push(1); dis[1] = 0;
memset(out, 0, sizeof(out)); out[1] = 1;
for(int i = 0; i <= n + 1; i++) pre[i] = i - 1, suf[i] = i + 1;
while(!q.empty()){
int x = q.front(); q.pop();
for(int i = first[x]; i; i = nxt[i]) vis[to[i]] = 1;
for(int i = 0; i != n + 1; i = suf[i]){
if(!vis[i] && !out[i]){
dis[i] = dis[x] + b;
q.push(i); del(i); out[i] = 1;
}
}
for(int i = first[x]; i; i = nxt[i]) vis[to[i]] = 0;
} cout << min((ll)a, dis[n]) << '\n';
}
void Yolanda(){
queue<int> q; q.push(1); dis[1] = 0;
while(!q.empty()){
int x = q.front(); q.pop();
for(int i = first[x]; i; i = nxt[i]){
int t = to[i]; if(dis[t] == inf){
dis[t] = dis[x] + a; q.push(t);
}
}
} cout << min((ll)b, dis[n]) << '\n';
}
int main(){
while(scanf("%d%d%d%d", &n, &m, &a, &b) != EOF){
memset(first, 0, sizeof(first)); tot = 0;
for(int i = 1; i <= n; i++) dis[i] = inf;
int flg = 0;
for(int i = 1; i <= m; i++){
int x = read(), y = read();
add(x, y); add(y, x);
if((x == 1 && y == n) || (x == n && y == 1)) flg = 1;
}
if(a == b) cout << a << '\n';
if(a < b){ if(flg == 1) cout << a << '\n'; else Yolanda();}
if(a > b){ if(flg == 0) cout << b << '\n'; else FSY();}
} return 0;
}
WOJ4701 Walk
考虑在
a
i
≤
1
e
6
a_i \le 1e6
ai≤1e6 下文章
我们可以类似线段树优化建图一样,每个二进制数向比它只少一个1的二进制数连边,边权为 0
每个点向它的二进制数连边,边权为1,每个二进制数向点连边,边权为0
然后就是
0
/
1
b
f
s
0/1 bfs
0/1bfs
#include<bits/stdc++.h>
#define N 200050 + (1<<20)
#define M 20300050
using namespace std;
int first[N], nxt[M], to[M], w[M], tot;
void add(int x, int y, int z){
nxt[++tot] = first[x], first[x] = tot, to[tot] = y, w[tot] = z;
}
int n, m, val[N], dis[N];
const int up = 1<<20;
void bfs(){
memset(dis, 63, sizeof(dis));
deque<int> q; q.push_front(1); dis[1] = 0;
while(!q.empty()){
int x = q.front(); q.pop_front();
for(int i = first[x]; i; i = nxt[i]){
int t = to[i]; if(dis[t] > dis[x] + w[i]){
dis[t] = dis[x] + w[i];
if(w[i] == 0) q.push_front(t);
else q.push_back(t);
}
}
}
}
int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) scanf("%d", &val[i]);
for(int i = 1; i <= m; i++){
int x, y; scanf("%d%d", &x, &y); add(x, y, 1);
}
for(int i = 1; i <= n; i++) add(i, val[i] + n+1, 1), add(val[i] + n+1, i, 0);
for(int i = 0; i < up; i++){
for(int j = 0; j < 20; j++){
int nxt = i | (1<<j);
if(i == nxt || nxt >= up) continue;
add(nxt + n+1, i + n+1, 0);
}
} bfs();
for(int i = 1; i <= n; i++) printf("%d\n", (dis[i] > 1e9) ? -1 : dis[i]);
return 0;
}
CF547D Mike and Fish
可以将行和列连边,这样子一个点的颜色就是这条边的颜色
然后一个点的出边一半是红,一半是蓝
如果将红看做入蓝看做出,那么走出来就是个欧拉回路
构造一下发现度数为奇数的点好像都是偶数个
所以如果度数是奇数的话就随便配对两两连边
#include<bits/stdc++.h>
#define N 800050
using namespace std;
int first[N], nxt[N], to[N], tot = 1;
void add(int x, int y){ nxt[++tot] = first[x], first[x] = tot, to[tot] = y;}
int vis[N], n, du[N];
void dfs(int u){
for(int &i = first[u]; i; i = nxt[i]){
int t = to[i]; if(vis[i] || vis[i^1]) continue;
vis[i] = 1; dfs(t);
}
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i++){
int x, y; scanf("%d%d", &x, &y); y += 2e5;
add(x, y); add(y, x); ++du[x]; ++du[y];
}
int lst = 0;
for(int i = 1; i <= 4e5; i++){
if(du[i] & 1){
if(lst) add(lst, i), add(i, lst), lst = 0;
else lst = i;
}
}
for(int i = 1; i <= 4e5; i++) if(du[i]) dfs(i);
for(int i = 1; i <= n; i++) putchar(vis[i << 1] ? 'b' : 'r');
return 0;
}