传送门: http://acm.hnu.cn/online/?action=problem&type=show&id=13313
Smoking gun |
Time Limit: 10000ms, Special Time Limit:25000ms, Memory Limit:65536KB |
Total submit users: 14, Accepted users: 7 |
Problem 13313 : No special judgement |
Problem description |
Andy: ”Billy the Kid fired first!” |
Input |
On the first line a positive integer: the number of test cases, at most 100. After that per test case: |
Output |
Per test case: |
Sample Input |
3 4 2 BillyTheKid 0 0 Andy 10 0 John 19 0 Larry 20 0 Andy heard BillyTheKid firing before John Larry heard John firing before BillyTheKid 2 2 Andy 0 0 Beate 0 1 Andy heard Beate firing before Andy Beate heard Andy firing before Beate 3 1 Andy 0 0 Beate 0 1 Charles 1 3 Beate heard Andy firing before Charles |
Sample Output |
BillyTheKid John IMPOSSIBLE UNKNOWN |
Problem Source |
HNU Contest |
题目意思:
n个人中的某些人发生一起枪战,police要确开枪人的开枪顺序,若能找到唯一顺序,则输出,若多组顺序则输出UNKNOWN,若无解,则IMPOSSIBLE
先给出n个人的二维平面上的坐标,然后给出m条信息。
A heard B firing before C 表示A先听到B的枪声,然后在听到C的枪声。
首先需要知道的是,只有一部分人开枪了,所有的判断操作都是针对那一部分人进行的。
(a,b,c)对于这样一组信息,若用dis[b][c]表示b比c先dis[b][c]的时间开枪,如果坐标上|ab|确实比|ac|远,那么我可以确定是b先开枪,否则,我不能确定谁先开枪。
最短路原理:(a,b,c)表示a->b有边权值c,那么dis[b]<=dis[a]+c。
此题: dist(b,c)<=dist(a,b)-dist(a,c) 即 dist(a,c)<=dist(a,b)-dist(b,c) 边为b->c权值为-dist(b,c)
那么可以依次考虑差分约束问题,建边dis[b][c]=dist(a,c)-dist(a,b) //取负值是为了Floyd判环,dis[i][i]<0出现负环,无解IMPOSSIBLE
最后确定顺序,找开枪的 i 满足dis[i][j]<0,那么i是先于其他人的,分别先|dist[i][j]|的时间,依次下去,直到找完所有的开枪人。
若个位置不能找到,那么是UNKNOWN
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<cmath>
#include<string>
using namespace std;
#define INF 0x3fffffff
map <string,int> mapt;
int n,m;
struct node{
int id;
double x,y;
char name[100];
node(double x_=0,double y_=0):x(x_),y(y_){}
void in(){scanf("%lf%lf",&x,&y);}
node operator - (node a){return node(x-a.x,y-a.y); }
double dis(){return sqrt(x*x+y*y);}
}p[110];
char s[100];
bool flag[110];
int ans[110];
int cnt;
string str;
void change(){
str="";
int len=strlen(s);
for(int j=0;j<len;j++)
str=str+s[j];
str=str+'\0';
}
double dist[110][110];
void floyed(){
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
}
int main(){
int T;scanf("%d",&T);
while(T--){
mapt.clear();
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dist[i][j]=(i==j)?0:INF;
for(int i=1;i<=n;i++){
flag[i]=false;
scanf("%s",s);
p[i].in();
strcpy(p[i].name,s);
change();
mapt[str]=i;
p[i].id=i;
}
for(int i=1;i<=m;i++){
//Andy heard BidoubleyTheKid firing before John
// a b c ==> if ab>=ac b->c = ac-ab
scanf("%s",s); change();
int a=mapt[str];
scanf("%s",s);
scanf("%s",s); change();
int b=mapt[str];
scanf("%s",s);scanf("%s",s);
scanf("%s",s); change();
int c=mapt[str];
dist[b][c]=min(dist[b][c],(p[a]-p[c]).dis()-(p[a]-p[b]).dis());
flag[b]=flag[c]=true;
}
floyed();
bool ok=true;
for(int i=1;i<=n;i++)if(flag[i])if(dist[i][i]<0){ok=false;break;}
if(ok==false)puts("IMPOSSIBLE");
else{
bool judge;
cnt=0;
for(int kk=1;kk<=n;kk++){
for(int i=1;i<=n;i++){
if(flag[i]){
judge=true;
for(int j=1;j<=n;j++){
if(i==j)continue;
if(flag[j]==false)continue;
if(dist[i][j]>=0){
judge=false;
break;
}
}
if(judge){
ans[cnt++]=i;
flag[i]=false;
break;
}
}
}
if(judge==false)break;
}
if(judge==false)puts("UNKNOWN");
else{
for(int i=0;i<cnt;i++)
printf("%s%c",p[ans[i]].name,i==cnt-1?'\n':' ');
}
}
}
return 0;
}
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define INF 0x3fffffff
struct node{
char name[110];
double x,y;
void in(){scanf("%s%lf%lf",name,&x,&y); }
}p[110];
double dist(node a,node b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); }
char tmp[110];
char s1[110],s2[110],s3[110];
int flag[110];
int order[110];
double dis[110][110];
int main(){
int T;scanf("%d",&T);
while(T--){
int n,m;scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
flag[i]=0;
for(int j=1;j<=n;j++)
dis[i][j]=(i==j)?0:INF;
}
for(int i=1;i<=n;i++)
p[i].in();
for(int i=1;i<=m;i++){
//Andy heard BidoubleyTheKid firing before John
scanf("%s%s%s%s%s%s",s1,tmp,s2,tmp,tmp,s3);
int a,b,c;
for(int j=1;j<=n;j++){
if(strcmp(s1,p[j].name)==0)a=j;
if(strcmp(s2,p[j].name)==0)b=j;
if(strcmp(s3,p[j].name)==0)c=j;
}
dis[b][c]=min(dis[b][c],dist(p[a],p[c])-dist(p[a],p[b]));//¸ºÖµ£¬Åл·
flag[b]=flag[c]=1;
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
bool neg=false;
int tot=0,cnt=0;
for(int i=1;i<=n;i++){
if(flag[i]==0)continue;
tot++;
if(dis[i][i]<0)neg=true;
}
if(neg==true){puts("IMPOSSIBLE");continue; }
bool judge;
while(tot--){
for(int i=1;i<=n;i++){
if(flag[i]==0)continue;
judge=true;
for(int j=1;j<=n;j++){
if(i==j)continue;
if(flag[j]==0)continue;
if(dis[i][j]>=0){
judge=false;
break;
}
}
if(judge==true){
order[cnt++]=i;
flag[i]=0;
break;
}
}
if(judge==false)break;
}
if(judge==false)puts("UNKNOWN");
else{
for(int i=0;i<cnt;i++)
printf("%s%c",p[order[i]].name,i==cnt-1?'\n':' ');
}
}
return 0;
}