100729 G 解题报告
题目链接:http://codeforces.com/gym/100729/attachments/download/3754/20112012-northwestern-european-regional-contest-nwerc-2011-en.pdf
这道题大概意思:
给你m个条件,n个人的坐标
"A听到,B比C先开枪"
然而,你需要考虑340m/s的声速的问题
所以,现在你要求出真正的开枪顺序,如果不能确定"UNKNOWN"信息有误"IMPOSSIBLE"
我们来考虑
A先听到B而不是C
那么就有B-->C的一条边
代表在C发枪val(b,c)秒后,B一定会发枪
那么我们floyd一次
如果出现val(i,i)<0,代表在i发枪前i秒,i一定会发枪,显然错,Impossible
如果出现val(i,j)>0且val(j,i)>0且i!=j,代表i和j之间发枪关系没定,显然Unknown了
其他情况,直接暴力找val全<0的即可.注意不要在任何时候去统计没发枪的人.
代码:
#include<set> #include<map> #include<list> #include<queue> #include<stack> #include<math.h> #include<string> #include<time.h> #include<bitset> #include<vector> #include<memory> #include<utility> #include<stdio.h> #include<sstream> #include<fstream> #include<iostream> #include<stdlib.h> #include<string.h> #include<algorithm> using namespace std; map<string,int> ma; int x[105],y[105]; char a[1005]; double dist[105][105]; double val[105][105]; bool gun[105]; string name[1005]; int main() { #ifdef absi2011 freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); #endif int t; scanf("%d",&t); int zu; for (zu=0;zu<t;zu++) { ma.clear(); int n,m; scanf("%d%d",&n,&m); int i; for (i=0;i<n;i++) { scanf("%s%d%d",a,&x[i],&y[i]); string b=a; ma[b]=i; name[i]=b; } for (i=0;i<n;i++) { int j; for (j=0;j<n;j++) { dist[i][j]=sqrt((double)(x[i]-x[j])*(x[i]-x[j])+(double)(y[i]-y[j])*(y[i]-y[j])); val[i][j]=1e12; } gun[i]=false; } int j,k; for (i=0;i<m;i++) { scanf("%s",a); string b=a; int x=ma[b]; scanf("%s",a); scanf("%s",a); b=a; int y=ma[b]; scanf("%s",a); scanf("%s",a); scanf("%s",a); b=a; int z=ma[b]; val[y][z]=min(val[y][z],dist[x][z]-dist[x][y]); gun[y]=true; gun[z]=true; } for (k=0;k<n;k++) { for (i=0;i<n;i++) { for (j=0;j<n;j++) { if ((k==i)||(k==j)) continue; val[i][j]=min(val[i][j],val[i][k]+val[k][j]); } } } for (i=0;i<n;i++) { if (val[i][i]<0) { puts("IMPOSSIBLE"); break; } } if (i!=n) continue; for (i=0;i<n;i++) { if (!gun[i]) continue; int j; for (j=0;j<n;j++) { if (!gun[j]) continue; if (i==j) continue; if ((val[i][j]>0)&&(val[j][i]>0)) { puts("UNKNOWN"); break; } } if (j!=n) break; } if (i==n) { for (k=0;k<n;k++) { for (i=0;i<n;i++) { if (!gun[i]) continue; for (j=0;j<n;j++) { if (!gun[j]) continue; if (i==j) continue; if (val[i][j]>0) break; } if (j==n) { printf("%s ",name[i].c_str()); gun[i]=false; break; } } } puts(""); } } return 0; }