题意:(转自http://blog.csdn.net/qq574857122/article/details/39121391)
给定n个点m条边的无向图,k个触发器。
下面k个数表示触发器安装在哪几个点。
下面m行给出边
最后有l个信号,
给出信号发出的触发器的顺序。
每个触发器只会发出一次信号,且一个点只有一个触发器。
有一个人在遍历图。
每经过一个点,那个点的触发器就会发出信号,问是否存在一种走法使得这个人遍历了所有点且触发器发出的信号顺序和给出的一样。
题解:
这一题就是标记+搜索。
所有未访问的标记为d[i]=0, 未访问的信号灯标记为d[i]=1;
可以访问的标记为 d[i]=-1;
第一个信号灯入栈,并且dfs,对于普通灯,直接标记为-1且入栈,
对于信号灯(比如灯k)呢,也标记为-1但是 不入栈,(表示灯k随时可以访问,因为已走过得路可以重新走嘛)。
然后对于每个信号灯都判断当前是否已经访问到(是否为-1),是-》继续,否 输出No
哎,比赛的时候,边E[] 数组木有初始化。。 泪奔~~~~~~~
代码:
#include <iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<stack>
#define MAXN 100000
typedef long long ll;
using namespace std;
int d[MAXN+5]; // 第i个pile是否被访问,1表示为信号灯,-1表示访问过
vector<int>E[MAXN+5];
int num[MAXN+5][2];
stack<int>Q;
int fa[MAXN+5];
/*
int getfather(int x)
{
if(fa[x]==-1) return x;
else return fa[x]=getfather(fa[x]);
}
void merge(int x,int y)
{
x=getfather(x);
y=getfather(y);
if(x==y) return;
if(x<y) fa[y]=x;
else fa[x]=y;
}
*/
int main()
{
int n,m,k,l;
int T,ok;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&m,&k);
memset(d,0,sizeof(d));
memset(fa,-1,sizeof(fa));
for(int i=1;i<=n;i++) E[i].clear(); // 没有初始化,导致无限WA
for(int i=1;i<=k;i++)
{
scanf("%d",&num[i][0]);
d[num[i][0]]=1;
}
for(int i=1;i<=m;i++)
{
int from,to;
scanf("%d%d",&from,&to);
E[from].push_back(to);
E[to].push_back(from);
// merge(from,to);
}
/* int flag=0;
for(int i=1;i<=n;i++)
if(fa[i]==-1) flag++;
// printf("flag=%d\n",flag);
flag=flag==1?1:0; */
scanf("%d",&l);
for(int i=1;i<=l;i++)
scanf("%d",&num[i][1]);
if(l<k) puts("No");
else{
ok=1;
num[l+1][1]=n+1;
d[n+1]=-1;
for(int i=1;i<=l;i++)
{
int now=num[i][1];
int nx=num[i+1][1];
d[num[i][1]]=-1;
while(!Q.empty()) Q.pop();
Q.push(now);
while(!Q.empty()){
int x=Q.top();
Q.pop();
for(int i=0;i<E[x].size();i++)
{
int indx=E[x][i];
if(d[indx]==1) //未访问的信号灯
d[indx]=-1;// 变为已访问,但是不入栈
else if(!d[indx]) //普通灯
{
Q.push(indx);//变为已访问,且入栈
d[indx]=-1;
}
}
}
if(d[nx]!=-1) { ok=0; break; }
}
for(int i=1;i<=n;i++)
if(!d[i]) {ok=0; break;}
if(ok ) puts("Yes");
else puts("No");
}
}
return 0;
}
还有一种 用星状链表做的:
复习一下~
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
#include<vector>
using namespace std;
typedef long long LL;
#define N 100010
#define M 400010
#define inf 2147483647
int n, m, Q, q, tot, ans;
int order[N], have[N], vis[N], head[N];
struct edge {
int u, v, next;
bool flag;
} ed[M];
void init() {
tot = 0;
ans = 1;
memset(have, 0, sizeof(have));
memset(vis, 0, sizeof(vis));
memset(head, -1, sizeof(head));
}
void add(int u, int v) {
ed[tot].u = u;
ed[tot].v = v;
ed[tot].flag = false;
ed[tot].next = head[u];
head[u] = tot++;
}
void dfs(int u) {
vis[u] = 1;
for (int i = head[u]; ~i; i = ed[i].next) {
int v = ed[i].v;
if (!vis[v] && !have[v])
dfs(v);
}
}
int main() {
int cas, i, u, v;
scanf("%d", &cas);
while (cas--) {
init();
scanf("%d%d%d", &n, &m, &Q);
for (i = 1; i <= Q; i++) {
scanf("%d", &u);
have[u] = 1;
}
for (i = 1; i <= m; i++) {
scanf("%d%d", &u, &v);
add(u, v);
add(v, u);
}
scanf("%d", &q);
for (i = 1; i <= q; i++)
scanf("%d", &order[i]);
if (Q != q)
ans = 0;
dfs(order[1]);
for (i = 2; i <= q; i++) {
v = 0;
for (u = head[order[i]]; ~u; u = ed[u].next) {
if (vis[ed[u].v]) {
v = 1;
break;
}
}
if (!v) {
ans = 0;
break;
}
dfs(order[i]);
}
for (i = 1; i <= n; i++) {
if (!vis[i]) {
ans = 0;
break;
}
}
if (ans)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}