除了1号点和n号点每个点度数小于等于2,因此1 到 n 的所有简单路径互不相交。
在结束游戏前的最后一步一定是剩下一条 1 到 n 的路径,并且路径上的权值全都是1。
游戏总步数确定,如果剩下的最后一条路径确定了,先后手的胜负就确定了。
那么双方的策略就使尽可能使最后留下的路径是使自己必胜的路径,即尽可能切断使对方必胜的路径。
如果先手Alice想赢:
- 若 初始时图中所有边的边权和为奇数:那么他一定要使剩下的最后一条路径有偶数条边(是边数,不是边权和),即他要在Bob把有偶数条边的路径拆完前把有奇数条边的路径拆完;
- 若 初始时图中所有边的边权和为偶数:那么他一定要使剩下的最后一条路径有奇数条边(是边数,不是边权和),即他要在Bob把有奇数条边的路径拆完前把有偶数条边的路径拆完;
切断一条路径需要的步数是这条路径上的权值的最小值。我们只需要比较双方切断对方必胜的路径所需要的步数即可。
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const int N=1e5+10;
const int M=150000;
const ll inf=1e9+7;
struct Edge{
int v,w,nxt;
}edge[M<<1];
int cnt,head[N],n,m;
ll sum,st[2];//st[0/1]:拆完有偶数/奇数条边的路径所需步数
void add(int u,int v,int w){
edge[++cnt].v=v;
edge[cnt].w=w;
edge[cnt].nxt=head[u];
head[u]=cnt;
}
void dfs(int u,int fa,ll minn,bool type){//type=0:路径有偶数条边,type=1:路径有奇数条边
if(u==n){
st[type]+=minn;
return;
}
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].v;
if(v==fa) continue;
dfs(v,u,min(minn,1ll*edge[i].w),type^1);
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);add(v,u,w);
sum+=1ll*w;
}
dfs(1,0,inf,0);
if(sum&1){
if(st[0]>=st[1]) printf("Yes\n");
else printf("No\n");
}
else{
if(st[0]<=st[1]) printf("Yes\n");
else printf("No\n");
}
return 0;
}