洛谷练习P2279 P1346
题目描述
2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地。起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了一个巨大的树状结构。如果基地A到基地B至少要经过d条道路的话,我们称基地A到基地B的距离为d。
由于火星上非常干燥,经常引发火灾,人类决定在火星上修建若干个消防局。消防局只能修建在基地里,每个消防局有能力扑灭与它距离不超过2的基地的火灾。
你的任务是计算至少要修建多少个消防局才能够确保火星上所有的基地在发生火灾时,消防队有能力及时扑灭火灾。
输入输出格式
输入格式:
输入文件名为input.txt。
输入文件的第一行为n (n<=1000),表示火星上基地的数目。接下来的n-1行每行有一个正整数,其中文件第i行的正整数为a[i],表示从编号为i的基地到编号为a[i]的基地之间有一条道路,为了更加简洁的描述树状结构的基地群,有a[i]<i。
输出格式:
输出文件名为output.txt
输出文件仅有一个正整数,表示至少要设立多少个消防局才有能力及时扑灭任何基地发生的火灾。
输入输出样例
6 1 2 3 4 5
2
http://www.cnblogs.com/candy99/p/6006145.html
简化版
问题在于不用考虑根节点一定是了
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> using namespace std; const int N=1005; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();} return x*f; } int n,v; struct edge{ int v,ne; }e[N<<1]; int h[N],cnt=0; void ins(int u,int v){ cnt++; e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt; cnt++; e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt; } struct node{ int u,d; node(int a=0,int b=0):u(a),d(b){} bool operator <(const node &r)const{return d>r.d;} }; node lst[N];int p=0; int d[N],fa[N],q[N],head,tail; void bfs(int s){ memset(d,-1,sizeof(d)); p=0; head=1;tail=0; q[++tail]=s; d[s]=0; fa[s]=0; while(head<=tail){ int u=q[head++],child=0; for(int i=h[u];i;i=e[i].ne){ int v=e[i].v; if(d[v]==-1){child++; d[v]=d[u]+1; fa[v]=u; q[++tail]=v; } } lst[++p]=node(u,d[u]); } } int vis[N]; void dfs(int u,int fa,int d){//printf("dfs %d %d\n",u,d); vis[u]=1; for(int i=h[u];i;i=e[i].ne){ int v=e[i].v; if(v!=fa&&d<2) dfs(v,u,d+1); } } int main(int argc, const char * argv[]) { n=read(); for(int i=1;i<=n-1;i++){v=read();ins(i+1,v);} bfs(1); sort(lst+1,lst+1+p); int ans=0; for(int i=1;i<=p;i++){//except s int u=lst[i].u;//printf("u %d\n",u); if(vis[u]) continue; for(int j=1;j<=2;j++) u=fa[u]; dfs(u,0,0); ans++; } printf("%d\n",ans); return 0; }
题目描述
在一个神奇的小镇上有着一个特别的电车网络,它由一些路口和轨道组成,每个路口都连接着若干个轨道,每个轨道都通向一个路口(不排除有的观光轨道转一圈后返回路口的可能)。在每个路口,都有一个开关决定着出去的轨道,每个开关都有一个默认的状态,每辆电车行驶到路口之后,只能从开关所指向的轨道出去,如果电车司机想走另一个轨道,他就必须下车切换开关的状态。
为了行驶向目标地点,电车司机不得不经常下车来切换开关,于是,他们想请你写一个程序,计算一辆从路口A到路口B最少需要下车切换几次开关。
输入输出格式
输入格式:
第一行有3个整数2<=N<=100,1<=A,B<=N,分别表示路口的数量,和电车的起点,终点。
接下来有N行,每行的开头有一个数字Ki(0<=Ki<=N-1),表示这个路口与Ki条轨道相连,接下来有Ki个数字表示每条轨道所通向的路口,开关默认指向第一个数字表示的轨道。
输出格式:
输出文件只有一个数字,表示从A到B所需的最少的切换开关次数,若无法从A前往B,输出-1。
输入输出样例
3 2 1 2 2 3 2 3 1 2 1 2
0
超水最短路一遍AC
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int N=105,INF=1e9+5; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } int n,s,v,st,ed; struct edge{ int v,w,ne; }e[N*N<<1]; int h[N],cnt=0; inline void ins(int u,int v,int w){ cnt++; e[cnt].v=v;e[cnt].w=w;e[cnt].ne=h[u];h[u]=cnt; } int q[N],head=1,tail=1; inline void lop(int &x){if(x==N) x=1;} int d[N],inq[N]; void spfa(){ for(int i=1;i<=n;i++) d[i]=INF; d[st]=0; head=tail=1; memset(inq,0,sizeof(inq)); q[tail++]=st; inq[st]=1; while(head!=tail){ int u=q[head++];inq[u]=0;lop(head); for(int i=h[u];i;i=e[i].ne){ int v=e[i].v,w=e[i].w; if(d[v]>d[u]+w){ d[v]=d[u]+w; if(!inq[v]){q[tail++]=v;inq[v]=1;lop(tail);} } } } } int main(){ n=read();st=read();ed=read(); for(int i=1;i<=n;i++){ s=read(); for(int j=1;j<=s;j++){ if(j==1) ins(i,read(),0); else ins(i,read(),1); } } spfa(); if(d[ed]==INF) puts("-1"); else printf("%d",d[ed]); }