最小树形图(有向图)

GGS-DDU http://acm.hdu.edu.cn/showproblem.php?pid=4966

建图待补,先做模板了。

  1 #include<cstdio>
  2 #include<cstring>
  3 #define mt(a,b) memset(a,b,sizeof(a))
  4 const int inf=0x3f3f3f3f;
  5 class Directed_MST { ///最小树形图(有向图)
  6     typedef int typec;///边权的类型
  7     static const int ME=250010;///边的个数
  8     static const int MV=550;///点的个数
  9     struct E {
 10         int u,v;
 11         typec w;
 12     } e[ME];
 13     int n,le,pre[MV],ID[MV],vis[MV];
 14     typec In[MV];
 15 public:
 16     void init() {
 17         le=0;
 18     }
 19     void add(int u,int v,typec w) {
 20         e[le].u=u;
 21         e[le].v=v;
 22         e[le].w=w;
 23         le++;
 24     }
 25     typec solve(int root,int tn) {///传入根和点的个数,点下标0开始
 26         n=tn;
 27         typec ret=0;
 28         while(true) {
 29             for(int i=0; i<n; i++) {
 30                 In[i]=inf;
 31             }
 32             for(int i=0; i<le; i++) {
 33                 int u=e[i].u;
 34                 int v=e[i].v;
 35                 if(e[i].w<In[v]&&u!=v) {
 36                     pre[v]=u;
 37                     In[v]=e[i].w;
 38                 }
 39             }
 40             for(int i=0; i<n; i++) {
 41                 if(i==root) continue;
 42                 if(In[i]==inf) return -1;///除了根以外有点没有入边,则根无法到达它
 43             }
 44             int cntnode=0;///找环
 45             mt(ID,-1);
 46             mt(vis,-1);
 47             In[root]=0;
 48             for(int i=0; i<n; i++) { ///标记每个环
 49                 ret+=In[i];
 50                 int v=i;
 51                 while(vis[v]!=i&&ID[v]==-1&&v!=root) {
 52                     vis[v]=i;
 53                     v=pre[v];
 54                 }
 55                 if(v!=root&&ID[v]==-1) {
 56                     for(int u=pre[v]; u!=v; u=pre[u]) {
 57                         ID[u]=cntnode;
 58                     }
 59                     ID[v]=cntnode++;
 60                 }
 61             }
 62             if(!cntnode) break;///无环
 63             for(int i=0; i<n; i++) {
 64                 if(ID[i]==-1) {
 65                     ID[i]=cntnode++;
 66                 }
 67             }
 68             for(int i=0; i<le; i++) { ///缩点,重新标记
 69                 int v=e[i].v;
 70                 e[i].u=ID[e[i].u];
 71                 e[i].v=ID[e[i].v];
 72                 if(e[i].u!=e[i].v) {
 73                     e[i].w-=In[v];
 74                 }
 75             }
 76             n=cntnode;
 77             root=ID[root];
 78         }
 79         return ret;
 80     }
 81 } gx;
 82 int n,m,a[550],s[550];
 83 int main() {
 84     while(~scanf("%d%d",&n,&m),n|m){
 85         for(int i=0;i<n;i++){
 86             scanf("%d",&a[i]);
 87             a[i]++;
 88         }
 89         s[0]=0;
 90         for(int i=0;i<n;i++){
 91             s[i+1]=a[i]+s[i];
 92         }
 93         gx.init();
 94         for(int i=0;i<n;i++){
 95             for(int j=s[i+1]-1;j>s[i];j--){
 96                 gx.add(j,j-1,0);
 97             }
 98             gx.add(s[n],s[i],0);
 99         }
100         while(m--){
101             int a,L1,b,L2,cost;
102             scanf("%d%d%d%d%d",&a,&L1,&b,&L2,&cost);
103             a--;
104             b--;
105             a=s[a]+L1;
106             b=s[b]+L2;
107             gx.add(a,b,cost);
108         }
109         printf("%d\n",gx.solve(s[n],s[n]+1));
110     }
111     return 0;
112 }

Transfer water http://acm.hdu.edu.cn/showproblem.php?pid=4009

待补,测模板。

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #define mt(a,b) memset(a,b,sizeof(a))
  5 using namespace std;
  6 typedef __int64 LL;
  7 const int inf=0x3f3f3f3f;
  8 const int M=1024;
  9 class Directed_MST { ///最小树形图(有向图)
 10     typedef int typec;///边权的类型
 11     static const int ME=M*M;///边的个数
 12     static const int MV=M;///点的个数
 13     struct E {
 14         int u,v;
 15         typec w;
 16     } e[ME];
 17     int n,le,pre[MV],ID[MV],vis[MV];
 18     typec In[MV];
 19 public:
 20     void init() {
 21         le=0;
 22     }
 23     void add(int u,int v,typec w) {
 24         e[le].u=u;
 25         e[le].v=v;
 26         e[le].w=w;
 27         le++;
 28     }
 29     typec solve(int root,int tn) {///传入根和点的个数,点下标0开始
 30         n=tn;
 31         typec ret=0;
 32         while(true) {
 33             for(int i=0; i<n; i++) {
 34                 In[i]=inf;
 35             }
 36             for(int i=0; i<le; i++) {
 37                 int u=e[i].u;
 38                 int v=e[i].v;
 39                 if(e[i].w<In[v]&&u!=v) {
 40                     pre[v]=u;
 41                     In[v]=e[i].w;
 42                 }
 43             }
 44             for(int i=0; i<n; i++) {
 45                 if(i==root) continue;
 46                 if(In[i]==inf) return -1;///除了根以外有点没有入边,则根无法到达它
 47             }
 48             int cntnode=0;///找环
 49             mt(ID,-1);
 50             mt(vis,-1);
 51             In[root]=0;
 52             for(int i=0; i<n; i++) { ///标记每个环
 53                 ret+=In[i];
 54                 int v=i;
 55                 while(vis[v]!=i&&ID[v]==-1&&v!=root) {
 56                     vis[v]=i;
 57                     v=pre[v];
 58                 }
 59                 if(v!=root&&ID[v]==-1) {
 60                     for(int u=pre[v]; u!=v; u=pre[u]) {
 61                         ID[u]=cntnode;
 62                     }
 63                     ID[v]=cntnode++;
 64                 }
 65             }
 66             if(!cntnode) break;///无环
 67             for(int i=0; i<n; i++) {
 68                 if(ID[i]==-1) {
 69                     ID[i]=cntnode++;
 70                 }
 71             }
 72             for(int i=0; i<le; i++) { ///缩点,重新标记
 73                 int v=e[i].v;
 74                 e[i].u=ID[e[i].u];
 75                 e[i].v=ID[e[i].v];
 76                 if(e[i].u!=e[i].v) {
 77                     e[i].w-=In[v];
 78                 }
 79             }
 80             n=cntnode;
 81             root=ID[root];
 82         }
 83         return ret;
 84     }
 85 } gx;
 86 int ha[M],hb[M],hc[M];
 87 int X,Y,Z;
 88 int dist(int i, int j) {
 89     int ret = abs(ha[i] - ha[j]) + abs(hb[i] - hb[j]) + abs(hc[i] - hc[j]);
 90     ret *= Y;
 91     if (hc[i] < hc[j]) ret += Z;
 92     return ret;
 93 }
 94 int main(){
 95     int n;
 96     while(~scanf("%d%d%d%d",&n,&X,&Y,&Z),n+X+Y+Z) {
 97         n++;
 98         gx.init();
 99         for (int i = 2; i <= n; i++) scanf("%d %d %d", &ha[i], &hb[i], &hc[i]);
100         for (int i = 2; i <= n; i++) {
101             gx.add(0,i-1,hc[i]*X);
102             int k;
103             scanf("%d", &k);
104             while (k--) {
105                 int j;
106                 scanf("%d", &j);
107                 j++;
108                 if (j != i) {
109                     int c = dist(i, j);
110                     gx.add(i-1,j-1,c);
111                 }
112             }
113         }
114         int ans=gx.solve(0,n);
115         if (ans==-1) puts("Impossible");
116         else printf("%d\n",ans);
117     }
118     return 0;
119 }

Command Network http://poj.org/problem?id=3164

距离建图,权值是double,模板题。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #define mt(a,b) memset(a,b,sizeof(a))
  5 const int inf=0x3f3f3f3f;
  6 const int M=128;
  7 class Directed_MST { ///最小树形图(有向图)
  8     typedef double typec;///边权的类型
  9     static const int ME=M*M;///边的个数
 10     static const int MV=M;///点的个数
 11     struct E {
 12         int u,v;
 13         typec w;
 14     } e[ME];
 15     int n,le,pre[MV],ID[MV],vis[MV];
 16     typec In[MV];
 17 public:
 18     void init() {
 19         le=0;
 20     }
 21     void add(int u,int v,typec w) {
 22         e[le].u=u;
 23         e[le].v=v;
 24         e[le].w=w;
 25         le++;
 26     }
 27     typec solve(int root,int tn) {///传入根和点的个数,点下标0开始
 28         n=tn;
 29         typec ret=0;
 30         while(true) {
 31             for(int i=0; i<n; i++) {
 32                 In[i]=inf;
 33             }
 34             for(int i=0; i<le; i++) {
 35                 int u=e[i].u;
 36                 int v=e[i].v;
 37                 if(e[i].w<In[v]&&u!=v) {
 38                     pre[v]=u;
 39                     In[v]=e[i].w;
 40                 }
 41             }
 42             for(int i=0; i<n; i++) {
 43                 if(i==root) continue;
 44                 if(In[i]==inf) return -1;///除了根以外有点没有入边,则根无法到达它
 45             }
 46             int cntnode=0;///找环
 47             mt(ID,-1);
 48             mt(vis,-1);
 49             In[root]=0;
 50             for(int i=0; i<n; i++) { ///标记每个环
 51                 ret+=In[i];
 52                 int v=i;
 53                 while(vis[v]!=i&&ID[v]==-1&&v!=root) {
 54                     vis[v]=i;
 55                     v=pre[v];
 56                 }
 57                 if(v!=root&&ID[v]==-1) {
 58                     for(int u=pre[v]; u!=v; u=pre[u]) {
 59                         ID[u]=cntnode;
 60                     }
 61                     ID[v]=cntnode++;
 62                 }
 63             }
 64             if(!cntnode) break;///无环
 65             for(int i=0; i<n; i++) {
 66                 if(ID[i]==-1) {
 67                     ID[i]=cntnode++;
 68                 }
 69             }
 70             for(int i=0; i<le; i++) { ///缩点,重新标记
 71                 int v=e[i].v;
 72                 e[i].u=ID[e[i].u];
 73                 e[i].v=ID[e[i].v];
 74                 if(e[i].u!=e[i].v) {
 75                     e[i].w-=In[v];
 76                 }
 77             }
 78             n=cntnode;
 79             root=ID[root];
 80         }
 81         return ret;
 82     }
 83 } gx;
 84 struct point{
 85     double x,y;
 86 }p[M];
 87 double Distance(point p1,point p2) {
 88     return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
 89 }
 90 int main(){
 91     int n,m,u,v;
 92     while(~scanf("%d%d",&n,&m)){
 93         for(int i=0;i<n;i++){
 94             scanf("%lf%lf",&p[i].x,&p[i].y);
 95         }
 96         gx.init();
 97         while(m--){
 98             scanf("%d%d",&u,&v);
 99             u--;
100             v--;
101             gx.add(u,v,Distance(p[u],p[v]));
102         }
103         double ans=gx.solve(0,n);
104         if(ans==-1) puts("poor snoopy");
105         else printf("%.2f\n",ans);
106     }
107     return 0;
108 }

end

时间: 2024-10-13 04:15:52

最小树形图(有向图)的相关文章

UVa11183 Teen Girl Squad, 最小树形图,朱刘算法

Teen Girl Squad Input: Standard Input Output: Standard Output You are part of a group of n teenage girls armed with cellphones. You have some news you want to tell everyone in the group. The problem is that no two of you are in the same room, and you

hdu 3072 有向图缩点成最小树形图计算最小权

题意,从0点出发,遍历所有点,遍历边时候要付出代价,在一个SCC中的边不要付费.求最小费用. 有向图缩点(无需建立新图,,n<=50000,建则超时),遍历边,若不在一个SCC中,用一个数组更新记录最小到达该连通分量的最小边权即可...边聊天,边1A,哈哈... #include<iostream> #include<stack> #include<queue> #include<cstdio> #include<cstring> usin

hdu 4009 Transfer water(最小树形图:有向图的最小生成树模板)

题目: 链接:点击打开链接 题意: 有n个村庄,要求使得每个村庄都能得到水的最小费用.每个村庄可以通过挖井或从其他村庄修水路获得水.挖井的费用是房子的高度乘以X,修水道的费用和有向图边的起点和终点的高度有关. 思路: 代码: #include <iostream> #include <cstdio> #include <cmath> #include <cstring> using namespace std; #define inf 0x3f3f3f3f

Directed_MST 最小树形图

List Directed_MST 最小树形图 List Knowledge 模板 Practice 参考资料 Knowledge 求一个图中遍历到每个点的方案中的最小边权和,显然n-1条边,即一颗树即可. 最小生成树?当然这里不是的,这里的最小树形图算法是针对有向图的. 最小树形图的第一个算法是1965年朱永津和刘振宏提出的复杂度为O(VE)的算法.简称朱刘算法. 1986年, Gabow, Galil, Spencer和Tarjan提出了一个复杂度更好的实现,其时间复杂度为O(E+VlogV

最小树形图【模板】

基于贪心和缩点的思想. 假设根的顶点是V0. (1)除了根结点外,所有的点Vi,找到以Vi为终点的最短的边,加入集合中 (pre[v]存放的是终点v的起点,In[v]存放终点为v的最短的边) (2)检查集合中有没有有向环和收缩点.若没有有向环和收缩点,结束计算:若没有有向环.但含收缩边,则跳至步骤(4):若含有有向环,则跳至步骤(3).Ps:如果出现重边,将忽略权值较高的 (3)含有有向环,则收缩有向环(缩点),把有向环收缩为一个点,其有向环内的边被收缩掉,而环外的边被保 留,构建新图,重复步骤

HDU2121 Ice_cream’s world II【最小树形图】【不定根】

Ice_cream's world II Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3005    Accepted Submission(s): 704 Problem Description After awarded lands to ACMers, the queen want to choose a city be he

poj Command Network 最小树形图

规定根节点,求一颗生成树使得权值最小,但由于是有向图,所以最小生成树算法失效. 查资料后得知此类问题叫做最小树形图. 解决最小树形图问题的朱刘算法,算法核心基于找 [最小弧集->找环,消环缩点] 的思想,来慢慢构造树形图. 所有的灵魂都在这张图上.0.0 注意缩点后的弧权值的处理 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algo

AIZU AOJ 2309 Vector Compression 最小树形图(朱—刘算法)

题意简述:给定若干个相同维度的向量,寻找一种排序方法,使得所有向量的表示长度总和最低. 所谓表示长度为(Aj-r*Ai)^2,其中i<j  数据范围:向量总数和维度均小于100 思路:(1)首先Ai和Aj确定后,最小表示长度是可以在线性时间计算出来的.使用简单的二次函数分析方法即可. (2)上述可以得出任意两向量之间的距离,即为图中的边,于是问题可以转化为有向图的"最小树形图",i到j的有向边权值即为用Aj表示Ai的最小表示长度. (3)朱-刘算法简述: 首先对除根以外的点选择一

POJ--3164--Command Network【朱刘算法】最小树形图

链接:http://poj.org/problem?id=3164 题意:告诉n个点坐标,m条边表示两个点之间有路.从1点開始建立一个有向图最小生成树. 朱刘算法模板题 ========================== 切割线之下摘自user_id=Sasuke_SCUT" style="color:rgb(202,0,0); text-decoration:none; font-family:Arial; font-size:14px; line-height:26px"