做hdu4009学习了最小树形图
。关于最小树形图的资料可以参看:最小树形图
Command Network
#include <cstdio>
#include <cstring>
const int maxn = 1005;
struct Edge{
int s, t, w;
}edge[maxn*maxn];
int ent;//记录边的数量
int n, X, Y, Z;
struct Point{
int x, y, z;
}pnt[maxn];
void addedge(int s, int t, int w){
edge[ent].s = s;
edge[ent].t = t;
edge[ent].w = w;
ent++;
}
int absv(int t){
if(t<0)
t = -t;
return t;
}
int manhattan(int i, int j){
int t = 0;
t = absv(pnt[i].x - pnt[j].x) +
absv(pnt[i].y - pnt[j].y)+
absv(pnt[i].z - pnt[j].z);
return t;
}
bool read(){
scanf("%d%d%d%d", &n, &X, &Y, &Z);
if(!n&&!X&&!Y&&!Z)
return false;
for(int i = 1; i <= n; i ++){
scanf("%d%d%d", &pnt[i].x, &pnt[i].y, &pnt[i].z);
}
ent = 0;
for(int i = 1; i <= n; i ++){
addedge(0, i, pnt[i].z * X);
}
int k, t;
for(int i = 1; i <= n; i ++){
scanf("%d", &k);
while(k--){
scanf("%d", &t);
if(pnt[i].z >= pnt[t].z)
addedge(i, t, manhattan(i,t)*Y);
else
addedge(i, t, manhattan(i,t)*Y+Z);
}
}
return true;
}
int in[maxn], pre[maxn], id[maxn], vis[maxn];
int dirmst(int r, int vs){
int ret = 0;
while(1){
int size = vs * 4;
memset(in, 0x3f, sizeof(in));
memset(id, -1, sizeof(id));
memset(vis, -1, sizeof(vis));
//step1: 找最小入弧
for(int i = 0; i < ent; i ++){
int s = edge[i].s;
int t = edge[i].t;
int w = edge[i].w;
if(w >= in[t] || s==t){
continue;
}
pre[t] = s;
in[t] = w;
}
in[r] = 0;
pre[r] = r;
for(int i = 0; i < vs ; i ++){
ret += in[i];
if(in[i]==0x3f3f3f3f)
return -1;
}
int idx = 0;
for(int i = 0; i < vs; i ++){
if(vis[i]==-1){
int u = i;
while(vis[u]==-1){
vis[u] = i;
u = pre[u];
}
if(vis[u] != i || u==r)
continue;
for(int t = pre[u]; t != u; t = pre[t])
id[t] = idx;
id[u] = idx ++;
}
}
if(idx==0)
break;
for(int i = 0; i < vs; i ++)
if(id[i]==-1)
id[i] = idx ++;
for(int i = 0; i < ent; i ++){
edge[i].w -= in[edge[i].t];
edge[i].s = id[edge[i].s];
edge[i].t = id[edge[i].t];
}
vs = idx;
r = id[r];
}
return ret;
}
void solve(){
int ans = dirmst(0, n+1);
if(ans==-1)
printf("poor XiaoA\n");
else
printf("%d\n", ans);
}
int main(){
while(read()){
solve();
}
return 0;
}
Command Network
#include <cstdio>
#include <cstring>
#include <cmath>
const int maxn = 105;
struct Point{
int x, y;
}pnt[maxn];
struct Edge{
int s, t;
double w;
}edge[maxn*maxn];
int n, m, ent;
double dist(int i, int j){
double t1 = 1.0*(pnt[i].x - pnt[j].x);
double t2 = 1.0*(pnt[i].y - pnt[j].y);
return sqrt(t1*t1 + t2*t2);
}
void addedge(int s, int t, double d){
edge[ent].s = s;
edge[ent].t = t;
edge[ent].w = d;
ent ++;
}
bool read(){
if(scanf("%d%d", &n, &m)==EOF){
return false;
}
for(int i = 1; i <= n; i ++){
scanf("%d%d", &pnt[i].x, &pnt[i].y);
}
ent = 0;
int s, t;
for(int i = 1; i <= m; i ++){
scanf("%d%d", &s, &t);
addedge(s, t, dist(s,t));
}
return true;
}
#define INF 1000000
double in[maxn];
int pre[maxn], id[maxn], vis[maxn];
double dirmst(int r, int vs){
double ret = 0;
while(1){
for(int i = 0; i <= vs; i ++){
in[i] = INF;
}
memset(id, -1, sizeof(id));
memset(vis, -1, sizeof(vis));
for(int i = 0; i < ent; i ++){
int s = edge[i].s;
int t = edge[i].t;
double w = edge[i].w;
if(w>=in[t] || s==t){
continue;
}
pre[t] = s;
in[t] = w;
}
in[r] = 0;
pre[r] = r;
for(int i = 1; i < vs; i ++){
ret += in[i];
if(in[i]>=INF)
return -1;
}
int idx = 1;
for(int i = 1; i < vs; i ++){
if(vis[i] == -1){
int u = i;
while(vis[u] == -1){
vis[u] = i;
u = pre[u];
}
if(vis[u] != i || u==r)
continue;
for(int t = pre[u]; t != u; t = pre[t]){
id[t] = idx;
}
id[u] = idx ++;
}
}
if(idx==1)
break;
for(int i = 1; i < vs; i ++){
if(id[i]==-1){
id[i] = idx ++;
}
}
for(int i = 0; i < ent; i ++){
edge[i].w -= in[edge[i].t];
edge[i].s = id[edge[i].s];
edge[i].t = id[edge[i].t];
}
vs = idx;
r = id[r];
}
return ret;
}
void solve(){
double ans = dirmst(1, n+1);
if(ans < 0)
puts("poor snoopy");
else
printf("%.2f\n", ans);
}
int main(){
while(read()){
solve();
}
return 0;
}