https://www.luogu.org/problem/show?pid=T2487
题目背景
小L那没出息的儿子当上了一个公交司机。
题目描述
每个司机都有一个牌子,牌子的正面标出了这个司机所开的线路号。另外一面则随便写了一个号码。但是,当小L的儿子拿到他的牌子时,却发现牌子的两面都不是他开的线路号,所以他决定跟其他人换。(真笨~不会找领导吗?)当然,所有的司机都只有当小L的儿子手里的牌子的某一面上写了自己的线路号时才愿意跟他换,所以,小L想知道自己的儿子至少要换几次牌子才能换到一张写有自己线路号的牌子。小L很急,所以他就拜托你去帮他了。
输入输出格式
输入格式:
第一行包含一个整数K ,表示车的数量。(小L的车除外)这些车的编号依次从1到K。
接下来的K行,每行包括此车对应的线路号和牌子另一面的号码(该号码是一个长整型范围内的数字)。
最后一行是安排小L开的公交车线路号以及给他的牌子上的号码。
输出格式:
输出文件只有1行,是最少交换次数M。
如果没有方案,则输出”IMPOSSIBLE”(引号不要输出)。
输入输出样例
输入样例#1:
4 8 5 5 4 7 4 1 5 4 1 8
输出样例#1:
2
说明
K<=1000。
数据保证线路号之间不重复。
升级版
【输出】
首行是最少交换的次数M,接下来的M行顺序输出要交换牌子的车的编号。如果没有方案,则输出IMPOSSIBLE。
题解
我们分别叫正面和背面A和B。两个点有边的条件是,A1=A2且B1=B2 或 A1=B2且B1=A2。
求出以n为源点的最短路,枚举每一个点。因为前面的交换都不需要满足路人丁,最后一次需要满足,所以最后一次要判断一下是否能够满足丁,然后找出最小值输出。
#include <string> #include <cstring> #include <cstdio> long dist[1010]; bool used[1010]; long a[1010]; long b[1010]; struct node { long ind; node* nxt; }; node* head[1010]; long g[1010]; long n; /* void output(long l) { if (!l) return; output(g[l]); printf("%ld ",l); } */ void dijkstra() { memset(dist,0x7f,sizeof dist); for (node* vv=head[n];vv;vv=vv->nxt) dist[vv->ind] = 1; used[n] = true; for (long l=1;l<n;l++) { long nearest = 0x7f7f7f7f; long u = 0; for (long i=1;i<n+1;i++) { if (dist[i]<nearest&&!used[i]) { nearest = dist[i]; u = i; } } used[u] = true; for (node* vv=head[u];vv;vv=vv->nxt) { long v = vv->ind; if (!used[v]&&dist[v]>dist[u]+1) { dist[v] = dist[u]+1; g[v] = u; } } } } long getint() { long rs=0;bool sgn=1;char tmp; do tmp = getchar(); while (!isdigit(tmp)&&tmp-'-'); if (tmp=='-'){tmp=getchar();sgn=0;} do rs=(rs<<3)+(rs<<1)+tmp-'0'; while (isdigit(tmp=getchar())); return sgn?rs:-rs; } void insert(long a,long b) { node* nn = new node; nn->ind = b; nn->nxt = head[a]; head[a] = nn; } int main() { // freopen("bus.in","r",stdin); // freopen("bus.out","w",stdout); n = getint(); for (long i=1;i<n+1;i++) { a[i] = getint(); b[i] = getint(); } long des = getint(); n ++; a[n] = getint(); b[n] = getint(); for (long i=1;i<n+1;i++) { for (long j=1;j<n;j++) { if (i == j) continue; if (a[i]==a[j]||b[i]==a[j]) { insert(i,j); } } } dijkstra(); long ans = 0x7f7f7f7f; long mov = 0; for (long i=1;i<n;i++) if (a[i]==des||b[i]==des) if (dist[i] < ans) { ans = dist[i]; mov = i; } if (ans == 0x7f7f7f7f) printf("IMPOSSIBLE"); else { printf("%ld ",ans); //output(mov); } return 0; }
快十倍的代码:
# include <iostream> # include <cstdio> # include <fstream> using namespace std; struct node { int t,f; }a[2000]; int visit[2000],q[2000],time1[2000],c[2000]; int main() { int n,i,t,n1,n2,ff,r,j,f,x,k; cin>>n; for (i=1;i<=n;i++) scanf("%d%d",&a[i].t,&a[i].f); cin>>t>>n1>>n2; r=0; for (i=1;i<=n;i++) if (a[i].t==n1 || a[i].t==n2) { r++; q[r]=i; visit[i]=1; time1[i]=1; if (a[i].f==t) { cout<<1<<endl; return 0; } } f=1; while (f<=r) { x=q[f]; for (i=1;i<=n;i++) if (a[i].t==a[x].f && !visit[i]) { r++; q[r]=i; visit[i]=1; time1[i]=time1[x]+1; if (a[i].f==t) { printf("%d ",time1[i]); return 0; } } f++; } cout<<"IMPOSSIBLE"<<endl; return 0; }