#include <bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i=(j);i<=(k);i++)
#define pb push_back
#define mem(a,k) memset(a,k,sizeof(a))
#define mp make_pair
typedef pair<int,int> P;
const int N = 1E5 + 7,inf = 0x3f3f3f3f;
struct node
{
int to,val;
};
vector<node>g[N];
int d[N],n,m,ans[N],vis[N];
void bfs1()
{
mem(d,-1);
d[n] = 0;
queue<P>que;
que.push(mp(n,0));
while(!que.empty()) {
P u = que.front(); que.pop();
for(int i = 0;i < g[u.first].size();i ++) {
int to = g[u.first][i].to;
if(d[to] == -1) {
d[to] = d[u.first] + 1;
que.push(mp(to,d[to]));
}
}
}
//for(int i = 1;i <= n;i ++) printf("%d ",d[i]);
}
void bfs2()
{
mem(ans,0x3f);
mem(vis,0);
queue<int>que;
que.push(1);
vis[1] = 1;
for(int i = 0;i < d[1];i ++) {
vector<int>tmp;
int res = inf;
while(!que.empty()) {
int u = que.front(); que.pop();
tmp.push_back(u);
for(int i = 0;i < g[u].size();i ++) {
int to = g[u][i].to, val = g[u][i].val;
if(d[to] == d[u]-1) {
res = min(res, val);
}
}
}
ans[i] = res;
for(int& it:tmp) {
for(auto& u:g[it]) {
int to = u.to, val = u.val;
if(d[to] == d[it]-1 && val == res && !vis[to]) {
que.push(to);
vis[to] = 1;
}
}
}
}
printf("%d\n",d[1]);
for(int i = 0;i < d[1];i ++) printf("%d%c",ans[i],i==d[1]-1?'\n':' ');
}
int main()
{
while(scanf("%d%d",&n,&m) == 2) {
rep(i,1,n) g[i].clear();
rep(i,1,m) {
int u, v, val;
scanf("%d%d%d",&u,&v,&val);
g[u].pb({v,val});
g[v].pb({u,val});
}
bfs1();
bfs2();
}
return 0;
}
UVA10129 题目链接:https://vjudge.net/contest/200148#problem/D
题意:输入n个单词,是否可以把所有这些单词排成一个序列,使得每个单词的第一个字母和上一个单词的最后一个字母相同,每个单词最多包含1000个小写字母,输入可以由重复。
题解:把字母看做节点,由于只是首位相连,每个单词只要首尾位即可,首位入度+1,末尾出度+1,合并。若有解,必须有欧拉路径。
先并查集看联通,然后判断度的关系即可。
#include <bits/stdc++.h>
using namespace std;
const int N = 30;
char s[1<<10];
int in[N], out[N], par[N], vis[N];
int find(int x){return x==par[x] ? x : par[x]=find(par[x]);}
void unit(int x, int y)
{
x = find(x), y = find(y);
if(x!=y) par[y] = x;
}
int main()
{
int T;
scanf("%d",&T);
while(T --) {
int n;
for(int i = 0;i < 26;i ++) par[i] = i;
memset(in, 0, sizeof(vis));
memset(out,0,sizeof(out));
scanf("%d",&n);
for(int i = 1;i <= n;i ++) {
scanf("%s",s);
int len = strlen(s);
in[s[0]-'a'] ++;
out[s[len-1]-'a'] ++;
unit(s[0]-'a', s[len-1]-'a');
}
int fg = 0;
for(int i = 0;i < 26;i ++) {
if((in[i]||out[i])&& i == par[i]) fg ++;
}
if(fg != 1) {
puts("The door cannot be opened.");
} else {
int dif = 0;
for(int i = 0;i < 26;i ++) {
if(in[i] != out[i]) dif ++;
}
if(dif != 2 && dif != 0) {
puts("The door cannot be opened.");
} else {
if(dif == 0) {
puts("Ordering is possible.");
} else {
vector<int>vec;
for(int i = 0;i < 26;i ++) {
if(in[i] != out[i]) {
vec.push_back(i);
}
}
assert(vec.size() == 2);
bool flag = 0;
if(in[vec[0]] == 1 + out[vec[0]] && in[vec[1]] == -1 + out[vec[1]]) flag = 1;
swap(vec[0], vec[1]);
if(in[vec[0]] == 1 + out[vec[0]] && in[vec[1]] == -1 + out[vec[1]]) flag = 1;
if(flag) puts("Ordering is possible.");
else puts("The door cannot be opened.");
}
}
}
}
return 0;
}
UVA1599
感觉这题很好紫书P1599,弱鸡只会2次BFS,感觉最妙的是第2次BFS,对每层BFS,取最优(好几个相同的话,都入队列)。
///
UVA11853
附上链接,看了这2个图和讲解终于知道怎么写了,难点在与从上放开始DFS,重点部分代码里标记了。
#include <bits/stdc++.h>
using namespace std;
const double R = 1000.0;
const int N = 1024;
int n;
pair<pair<int,int>,int>cir[N];
#define fi first
#define se second
double left_,right_;
bool vis[N];
inline bool ins(int a,int b)
{
return hypot(fabs(cir[a].fi.fi-cir[b].fi.fi),fabs(cir[a].fi.se-cir[b].fi.se)) < cir[a].se + cir[b].se;
}
void update(int a)
{
//附上链接里图片很好说明这2个更新
if(cir[a].fi.fi - cir[a].se < 0) left_ = min(left_, cir[a].fi.se - sqrt(cir[a].se*cir[a].se-cir[a].fi.fi*cir[a].fi.fi)); .
if(cir[a].fi.fi + cir[a].se > R) right_ = min(right_, cir[a].fi.se - sqrt(cir[a].se*cir[a].se-(R-cir[a].fi.fi)*(R-cir[a].fi.fi)));
}
bool dfs(int u)
{
if(vis[u]) return false;
vis[u] = 1;
if(cir[u].fi.se < cir[u].se) return true; //某次这个圆与下方x轴接触了,则一定封闭了图形,无解
for(int i = 0;i < n;i ++) {
if(ins(u,i) && dfs(i)) return true;
}
update(u);
return false;
}
int main()
{
std::ios::sync_with_stdio(false), cin.tie(0);
while(cin >> n) {
memset(vis, 0, sizeof(vis));
left_ = right_ = 1000;
for(int i = 0;i < n;i ++) cin >> cir[i].fi.fi >> cir[i].fi.se >> cir[i].se;
bool ok = true;
for(int i = 0;i < n;i ++) {
if(cir[i].fi.se+cir[i].se >= R && dfs(i)) { //说明与上方有接触,有可能形成封闭的图形,dfs才有意义。
ok = false; break;
}
}
if(ok) {
cout << fixed << setprecision(2) << "0.00 " << left_ << " 1000.00 " << right_ << '\n';
} else {
cout << "IMPOSSIBLE\n";
}
}
return 0;
}