Memory limit: 512 megabytes
给定一个有 n 个点和 m 条边的无向图,其中每一条边 ei 都有一个权值记为 wi 。
对于给出的两个点 a 和 b ,求一条 a 到 b 的路径,使得路径上的边权的 OR(位或)和最小,输出这个值。(也就是说,如果将路径看做边的集合 {e1,e2,…,ek} ,那么这条路径的代价为 w1ORw2OR…ORwk ,现在求一条路径使得其代价最小,输出这个代价。) 如果不存在这样的路径,输出 −1 。
Input
第一行两个数
n
和
m
。
接下来
m
行,每行三个数
ui,vi,wi
,表示有一条
ui
到
vi
的权值为
wi
的无向边。
最后一行两个数
a,b
,分别表示起点和终点。
- 2≤n≤103,0≤m≤104,0≤ci≤210−1
- 1≤ui,vi,a,b≤n,a≠b
可能有重边和自环。
Output
在一行中输出一个最小代价,如果无解输出 −1 。
Examples
3 4 1 2 2 1 2 4 1 3 5 2 3 3 1 2
2
Note
图中可能会有重边。
用DFS。
建图的时候一开始用的邻接表,结果我们在枚举某个点指向的各个点时,我们还需要两者之间边的信息(w)。用邻接表只能获得点,所以不行。
而数组也更不可以,因为有重边。
所以用 vector< pair<int,int> >Edge[n+1]; 来存放。可以获得点和边的信息。
建立一个vis【a】【b】,记录到达a点时,代价为b是否存在。
利用bfs,建立两个queue,一个存放点(当前到达了那个点),一个存放代价(到达当前点是的代价为多少)。
我们遍历下一个点,vis[a][b|w]=1。不管三七二十一把所有的情况都遍历完。
之后我们代价从1-1024开始枚举。
找最小代价,也就是到达vis[b][i]。如果存在,那么输出i,break即可。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,m;
bool vis[1100][1100];
cin>>n>>m;
vector< pair<int,int> >Edge[n+1];
for(int i=0;i<m;i++)
{
int a,b,c;
cin>>a>>b>>c;
Edge[a].push_back(make_pair(b,c));
Edge[b].push_back(make_pair(a,c));
}
int a,b;
cin>>a>>b;
memset(vis,false,sizeof(vis));
vis[a][0]=true;
queue<int>que1;
queue<int>que2;
que1.push(a);
que2.push(0);
while(!que1.empty())
{
int qu1=que1.front();
int qu2=que2.front();
que1.pop();
que2.pop();
for(pair<int,int>b:Edge[a])
{
pair<int,int>dangqian=b;
if(!vis[dangqian.first][qu2|dangqian.second])
{
vis[dangqian.first][qu2|dangqian.second]=true;
que1.push(dangqian.first);
que2.push(dangqian.second|qu2);
}
}
}
int flag=0;
for(int i=1;i<=n;i++)
{
if(vis[b][i])
{
cout<<i<<endl;
flag=1;
break;
}
}
if(flag)
{
}
else
{
cout<<"-1"<<endl;
}
}