帝国布线 十分恶心的加边图论题

帝国布线 十分恶心的加边图论题_第1张图片

 

 分析?

  看见这题第一眼,这什么鬼??看不懂。/

  还好有万能的老师,解释一通后大概明白了,这不就是最短路??于是准备大展身手瞎打一下试试 , 写输入的时候我犹豫了,emm,貌似只有三个点?还是任意的三个点?哇那这很难受啊,所以这道题其实最难的地方是什么,求出第四个点的坐标,由三个任意点可以想到什么呢,三角形,三角形是什么?矩形的一半,所以枚举三角形的三条边,最长的那一条就是矩形对角线,对角线的两端已经确定,可以求出对角线中点,中点有了,剩下的那个点也就好求了(感谢初中数学老师)。

  然后就跑一个最短路就行了,看数据范围好像Floyd也可以,但不敢用,万一炸了那不就gg?图中没有负权,所以写了一个Dij,有一个点注意下就是一座城市有四个出发点,所以可以跑四遍Dij,但这样是不是很麻烦,所以我建了一个超级源点,让这个点到四个点的距离为0,然后从这个点开始最短路,最后看看到B的那个点最短输出就行。

  

  1 #include
  2 #include
  3 #include
  4 #include
  5 #include
  6 using namespace std;
  7 typedef double d;
  8 const int N=1e5+10;
  9 const d INF=0x3f3f3f3f;
 10 struct Edge{
 11     int to,next;
 12     d val;
 13 }e[N];
 14 struct Node{
 15     d x,y;
 16 }p[N];
 17 int Head[N],len,num;
 18 void Ins(int a,int b,d c){
 19     e[++len].to=b;e[len].val=c;
 20     e[len].next=Head[a];Head[a]=len;
 21 }
 22 d dis(d x,d y,d xx,d yy){
 23     return sqrt((x-xx)*(x-xx)+(y-yy)*(y-yy));
 24 }
 25 d X1,Y1,X2,Y2,X3,Y3,X4,Y4,dist[N];
 26 void point(){
 27     d a=dis(X1,Y1,X2,Y2),
 28       b=dis(X1,Y1,X3,Y3),
 29       c=dis(X2,Y2,X3,Y3);
 30     d Max=max(a,max(b,c));
 31     d mix,miy,mxx,mxy,x,y;
 32     if(Max==a)mix=X1,miy=Y1,mxx=X2,mxy=Y2,x=X3,y=Y3;
 33     if(Max==b)mix=X1,miy=Y1,mxx=X3,mxy=Y3,x=X2,y=Y2;
 34     if(Max==c)mix=X2,miy=Y2,mxx=X3,mxy=Y3,x=X1,y=Y1;
 35     d midx=(mix+mxx)/2,midy=(miy+mxy)/2;
 36     X4=2*midx-x;Y4=2*midy-y;
 37 }
 38 d ans,m,belong[N];int fro,tto,n;bool vis[N];
 39 void init(){
 40     len=num=0;
 41     ans=INF;
 42     memset(Head,0,sizeof(Head));
 43     memset(belong,0,sizeof(belong));
 44     memset(p,0,sizeof(p));
 45     memset(vis,0,sizeof(vis));
 46 }
 47 struct node{
 48     int id;d diss;
 49     node(){}
 50     node(int a,d b){
 51         id=a;diss=b;
 52     }
 53     bool operator < (const node &A)const {
 54         return diss>A.diss;
 55     }
 56 };
 57 void dij(){
 58     priority_queue q;
 59     q.push(node(0,0));
 60     dist[0]=0;
 61     while(!q.empty()){
 62         node u=q.top();q.pop();
 63         if(vis[u.id])continue;
 64         vis[u.id]=1;
 65         for(int x=Head[u.id];x;x=e[x].next){
 66             int v=e[x].to;
 67             if(dist[v]>dist[u.id]+e[x].val){
 68                 dist[v]=dist[u.id]+e[x].val;
 69                 q.push(node(v,dist[v]));
 70             }
 71         }
 72     }
 73 }
 74 int main(){
 75     freopen("car.in","r",stdin);
 76     freopen("car.out","w",stdout);
 77     int t;
 78     scanf("%d",&t);
 79     while(t--){
 80         init();
 81         scanf("%d%lf%d%d",&n,&m,&fro,&tto);
 82         for(int i=1;i<=n;i++){
 83             scanf("%lf%lf%lf%lf%lf%lf%lf",&X1,&Y1,&X2,&Y2,&X3,&Y3,&belong[i]);
 84             point();
 85             p[++num].x=X1,p[num].y=Y1;
 86             p[++num].x=X2,p[num].y=Y2;
 87             p[++num].x=X3,p[num].y=Y3;
 88             p[++num].x=X4,p[num].y=Y4;
 89         }
 90         for(int i=1;i<=num;i++)
 91             dist[i]=INF;
 92         for(int i=1;i<=num;i++){
 93             for(int j=1;j<=num;j++){
 94                 if(i==j)continue;
 95                 int c1=(i-1>>2)+1,c2=(j-1>>2)+1;
 96                 if(c1==c2){
 97                     d c=dis(p[i].x,p[i].y,p[j].x,p[j].y)*belong[c1];
 98                     Ins(i,j,c);
 99                     Ins(j,i,c);
100                 }else {
101                     d c=dis(p[i].x,p[i].y,p[j].x,p[j].y)*m;
102                     Ins(i,j,c);
103                     Ins(j,i,c);
104                 }
105             }
106         }
107         for(int i=(fro-1<<2)+1;i<=fro<<2;i++){
108             Ins(0,i,0);Ins(i,0,0);
109         } 
110         dij();
111         for(int i=(tto-1<<2)+1;i<=tto<<2;i++)ans=min(dist[i],ans);
112         printf("%.1lf\n",ans);
113     }
114     return 0;
115 }
Code

  由于太长了所以我直接折叠了吧。。

  

帝国布线 十分恶心的加边图论题_第2张图片

 

                                    超级喜欢太阳 PS:图片来源zsy

 

你可能感兴趣的:(帝国布线 十分恶心的加边图论题)