题目:
思路:这题简单极了。。。然而我一上午都被Yveh叫去擦玻璃。。。
设计状态
f(i,0/1,0/1)
表示在节点
i
,第一个
当然实际上
std
的解法与此相似,只是更简洁,而且这道题是可以用最小割做的,虽然
105
但跑的飞快。
代码:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#define N 100002
#define inf 1e9
using namespace std;
struct edge { int nxt,point,v;};
typedef long long LL;
edge e[N << 1];
int cnt,n,m,fa[N];
LL f[N][2][2],ans;
bool vis[N],ex[N];
void add(int u1,int v1){
e[++cnt].nxt = e[u1].point; e[u1].point = cnt; e[cnt].v = v1; }
void insert(int u1,int v1){ add(u1,v1); add(v1,u1); }
void init(){
int u1,v1;
scanf("%d%d",&n,&m);
cnt = 0;
for (int i = 1;i <= n; ++i){
scanf("%d%d",&u1,&v1);
insert(u1,v1);
}
memset(ex,0,sizeof(ex));
for (int i = 1;i <= m; ++i){
scanf("%d",&u1);
ex[u1] = 1;
}
memset(fa,0,sizeof(fa));
fa[0] = -1;
ans = inf;
}
void up_lef(int x){
if (ex[x]) { ans = -1; return; }
f[x][1][1] = f[x][1][0] = inf;
f[x][0][1] = 0; f[x][0][0] = 1;
}
void up_enemy(int x){
f[x][0][0] = f[x][0][1] = f[x][1][1] = inf;
for (int p = e[x].point;p;p = e[p].nxt)
if (e[p].v != fa[x]){
f[x][1][0] += min(f[e[p].v][1][0],f[e[p].v][0][0]);
}
}
void up_nothing(int x){
f[x][1][0] = f[x][1][1] = inf;
f[x][0][0] = f[x][0][1] = 1;
for (int p = e[x].point;p;p = e[p].nxt)
if (e[p].v != fa[x]){
int j = e[p].v;
f[x][0][0] += min(f[j][1][0],min(f[j][0][1],f[j][0][0]));
f[x][0][1] += min(f[j][1][0],min(f[j][0][1],f[j][0][0]));
}
LL s1 = 0,s2 = 0,s3 = 0;
for (int p = e[x].point;p;p = e[p].nxt)
if (e[p].v != fa[x]){
int j = e[p].v;
s1 += f[j][0][0];
s2 += min(f[j][0][0],f[j][0][1]);
s3 += min(f[j][0][0],f[j][1][0]);
}
f[x][0][0] = min(f[x][0][0],s1);
f[x][0][1] = min(f[x][0][1],s2);
f[x][1][0] = min(f[x][1][0],s3);
}
void dfs(int x){
bool lef = 1;
for (int p = e[x].point;p;p = e[p].nxt)
if (e[p].v != fa[x]){
lef = 0;
fa[e[p].v] = x;
dfs(e[p].v);
}
if (lef) up_lef(x);
else
if (ex[x]) up_enemy(x);
else up_nothing(x);
}
void DO_IT(){
memset(vis,0,sizeof(vis));
dfs(0);
LL s = 0;
for (int p = e[0].point;p;p = e[p].nxt)
++s;
if (s == 1)
if (ex[0]) ans = -1;
else f[0][1][0]++;
ans = min(ans,min(min(f[0][0][0],f[0][0][1]),f[0][1][0]));
if (ans >= inf) ans = -1;
}
int main(){
init();
DO_IT();
cout<<ans;
return 0;
}
总结: