EOJ Monthly 2018.1 F1. 最小 OR 路径 (EASY) 新的建图方式+vis同时记录点和代价
2018-01-23 15:26
246 查看
Memory limit: 512 megabytes
给定一个有
n
个点和
m
条边的无向图,其中每一条边
ei
都有一个权值记为
wi。
对于给出的两个点
a
和
b,求一条
a
到
b
的路径,使得路径上的边权的 OR(位或)和最小,输出这个值。(也就是说,如果将路径看做边的集合
{e1,e2,…,ek},那么这条路径的代价为
w1ORw2OR…ORwk,现在求一条路径使得其代价最小,输出这个代价。)
如果不存在这样的路径,输出
−1。
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
可能有重边和自环。
−1。
Output
用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;
}
}
给定一个有
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
Input3 4 1 2 2 1 2 4 1 3 5 2 3 3 1 2
Output
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;
}
}
相关文章推荐
- POJ 1734 Sightseeing trip (Floyd 最小环+记录路径)
- POJ 1734 Sightseeing trip【floyd求最小环+记录路径】
- ECNU 3462. 最小 OR 路径 [dfs+枚举]
- HDU 3991 Harry Potter and the Present II 最小路径覆盖 建图
- php删除页面记录 同时刷新页面 删除条件用GET方式获得
- HDOJ 5294 Tricks Device 最短路(记录路径)+最小割
- hdu-携程复赛-最短路径的代价-抠图+最小割
- SCU 4529 An Easy Problem(强连通分量+缩点+最小路径覆盖+剪枝)
- 有一条记录,其中有一个字段是图片路径,删除记录同时也要删除图片的执行顺序?
- 查Name相同ID最小的记录的多種方式
- poj1734Sightseeing trip【floyd+最小环+路径记录】
- 最小生成树(不记录路径)
- drupal7 创建form表单 并重定向提交路径同时使用get方式传递(drupal 简洁url)传参实例演示
- php删除页面记录 同时刷新页面 删除条件用GET方式获得
- 2、 excel 导出。这种输入方式,适合后台输出,不需要打开EXCEL文件,不需要选择输出路径,只是后台自己默默的记录EXCEL文件。
- uvaoj 116 Unidirectional TSP 动态规划记录字典序最小路径
- poj 1734 Sightseeing trip_ 最小环记录路径
- 在大容量导入中按最小方式记录日志的前提条件
- poj3984~用bfs求最短路~同时记录路径
- HDU携程决赛最短路径的代价/USTC 1280 Finding Shortest Path 求最短路边+最小割