最小乘积生成树

详情请看:唐文斌在国家冬令营的讲课

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<queue>
  6 #include<ctime>
  7 using namespace std;
  8 #define MAXN 210
  9 #define MAXM 11000
 10 const long long INF=10000000000000000ll;
 11 long long ans=INF;
 12 pair<long long,long long> e;
 13 struct Edge
 14 {
 15     int x,y;
 16     long long w1,w2;
 17 };
 18 struct node
 19 {
 20     int num,id;
 21     long long weight;
 22     node *next;
 23 };
 24 Edge edge[MAXM];
 25 node *graph[MAXN],memo[2*MAXM];
 26 int n,m,top=0;
 27 bool use[MAXN];
 28 long long d[MAXN];
 29 priority_queue<pair<long long,pair<int,int> >,vector<pair<long long,pair<int,int> > >,greater<pair<long long,pair<int,int> > > > Q;
 30 void add(int x,int y,long long w,int id)
 31 {
 32     node *p=&memo[top++];
 33     p->num=y; p->weight=w; p->id=id; p->next=graph[x]; graph[x]=p;
 34     p=&memo[top++];
 35     p->num=x; p->weight=w; p->id=id; p->next=graph[y]; graph[y]=p;
 36 }
 37 pair<long long,long long> prim()
 38 {
 39     long long x=0,y=0;
 40     long long w;
 41     int i,u,v,id;
 42     memset(use,0,sizeof(use));
 43     for(i=0;i<n;i++)
 44         d[i]=INF;
 45     d[0]=0;
 46     while(!Q.empty()) Q.pop();
 47     Q.push(make_pair(0,make_pair(0,0)));
 48     for(i=1;i<=n;i++)
 49     {
 50         if(Q.empty()) break;
 51         u=Q.top().second.first;
 52         id=Q.top().second.second;
 53         Q.pop();
 54         while(!Q.empty()&&use[u])
 55         {
 56             u=Q.top().second.first;
 57             id=Q.top().second.second;
 58             Q.pop();
 59         }
 60         
 61         use[u]=1;
 62         x+=edge[id].w1;
 63         y+=edge[id].w2;
 64         for(node *p=graph[u];p;p=p->next)
 65         {
 66             v=p->num;
 67             if(!use[v]&&d[v]>p->weight)
 68             {
 69                 d[v]=p->weight;
 70                 Q.push(make_pair(d[v],make_pair(v,p->id)));
 71             }
 72         }
 73     }
 74     if(x*y<ans)
 75     {
 76         ans=x*y;
 77         e=make_pair(x,y);
 78     }
 79     return make_pair(x,y);
 80 }
 81 
 82 pair<long long,long long> make_graph(long long k1,long long k2)
 83 {
 84     memset(graph,0,sizeof(graph));
 85     int i;
 86     top=0;
 87     for(i=1;i<=m;i++)
 88         add(edge[i].x,edge[i].y,edge[i].w1*k1+edge[i].w2*k2,i);
 89     return prim();
 90 }
 91 void make(pair<long long,long long> tree1,pair<long long,long long> tree2)
 92 {
 93     if(tree1==tree2) return ;
 94     long long temp1=tree2.first-tree1.first;
 95     long long temp2=tree1.second-tree2.second;
 96     pair<long long,long long> tree3=make_graph(temp2,temp1);
 97     if(tree3.first>tree1.first&&tree2.first>tree3.first&&tree3.second<tree1.second&&tree2.second<tree3.second) 
 98     {
 99         make(tree1,tree3);
100         make(tree3,tree2);
101     }
102 }
103 
104 void solve()
105 {
106     int i;
107     pair<long long,long long> tree1,tree2;
108     tree1=make_graph(1,0);
109     tree2=make_graph(0,1);
110     make(tree1,tree2);
111     printf("%I64d %I64d\n\n",e.first,e.second);
112 }
113 int main()
114 {
115     int i;
116     memset(edge,0,sizeof(edge));
117     scanf("%d%d",&n,&m);
118     for(i=1;i<=m;i++)
119         scanf("%d%d%I64d%I64d",&edge[i].x,&edge[i].y,&edge[i].w1,&edge[i].w2);
120     solve();
121     //cout<<clock()<<endl;
122     return 0;
123 }

posted on 2012-05-31 19:37  myoi  阅读(932)  评论(0编辑  收藏  举报

导航