POJ 1639 最小度限制生成树 http://poj.org/problem?id=1639
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<ctype.h>
#include<algorithm>
#include<stack>
#include<queue>
using namespace std;
#define maxn 22
int n,k;
int e1[maxn][maxn];
int e2[maxn][maxn];
struct Edge{
int u,v,w;
Edge(int a,int b,int c){u=a,v=b,w=c;}
bool friend operator< (Edge a,Edge b){
return a.w>b.w;
}
};
priority_queue<Edge> q;
char name[maxn][12];
int l;
char s1[12],s2[12];
int get_id(char *p){
for(int i=0;i<l;i++){
if(strcmp(p,name[i])==0)
return i;
}
strcpy(name[l],p);
l++;
return l-1;
}
int bin[maxn];
int find(int a){
if(bin[a]!=a) bin[a]=find(bin[a]);
return bin[a];
}
bool get(int a,int b){
int x=find(a);
int y=find(b);
if(x!=y) {bin[y]=x;return 1;}
return 0;
}
void dfs(int u,int fa){
for(int i=1;i<l;i++){
if(e2[u][i]==1&&i!=fa){
get(u,i);
dfs(i,u);
}
}
}
void Print_ans(){
int ans=0;
for(int i=0;i<l;i++)
for(int j=i+1;j<l;j++)
if(e2[i][j]==1)
ans+=e1[i][j];
printf("Total miles driven: %d\n",ans);
}
void solve(){
int cnt=0;
for(int i=0;i<=l;i++) bin[i]=i;
while(!q.empty()){
Edge e=q.top();
q.pop();
if(get(e.u,e.v)){
if(e.u==0||e.v==0) cnt++;
e2[e.u][e.v]=e2[e.v][e.u]=1;
}
}
for(int i=0;i<=l;i++) bin[i]=i;
for(int j=1;j<l;j++){
if(e2[0][j]==1) dfs(j,0);
}
while(cnt>k){
int x,y,mmin=1000000;
for(int i=1;i<l;i++){
for(int j=i+1;j<l;j++){
if(e1[i][j]!=0&&e2[i][j]==0){
int i1=find(i);
int j1=find(j);
if(i1==j1) continue;
int mmax=max(e1[0][i1],e1[0][j1]);
if(mmin>(e1[i][j]-mmax)){
mmin=e1[i][j]-mmax;
x=i; y=j;
}
}
}
}
cnt--;
e2[x][y]=1,e2[y][x]=1;
int x1=find(x),y1=find(y);
if(e1[0][x1]>e1[0][y1]) e1[0][x1]=e1[x1][0]=0,get(y1,x1);
else e1[0][y1]=e1[y1][0]=0,get(x1,y1);
}
Print_ans();
}
void init(){
strcpy(name[0],"Park");
l=1;
memset(e1,0,sizeof(e1));
memset(e2,0,sizeof(e2));
while(!q.empty()) q.pop();
for(int i=0;i<n;i++){
int w;
scanf("%s%s%d",s1,s2,&w);
int d1=get_id(s1);
int d2=get_id(s2);
q.push(Edge(d1,d2,w));
e1[d1][d2]=e1[d2][d1]=w;
}
scanf("%d",&k);
}
int main(){
while(scanf("%d",&n)!=EOF){
init();
solve();
}
}
HDU 2121最小树形图(无固定根) http://acm.hdu.edu.cn/showproblem.php?pid=2121
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <ctime>
#include <queue>
#include <map>
#include <sstream>
#define CL(arr, val) memset(arr, val, sizeof(arr))
#define REP(i, n) for((i) = 0; (i) < (n); ++(i))
#define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i))
#define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i))
#define L(x) (x) << 1
#define R(x) (x) << 1 | 1
#define MID(l, r) (l + r) >> 1
#define Min(x, y) x < y ? x : y
#define Max(x, y) x < y ? y : x
#define E(x) (1 << (x))
const double eps = 1e-6;
const double inf = ~0u>>1;
typedef long long LL;
using namespace std;
const int N = 1100; // 调整
const int M = 20010; // 调整
struct node { //可删
double x, y;
} point[N];
double SQ(int u, int v) { // 可删
return sqrt((point[u].x - point[v].x)*(point[u].x - point[v].x) +
(point[u].y - point[v].y)*(point[u].y - point[v].y));
}
struct edg {
int u, v;
int cost; //double
} E[M];
int In[N]; //double
int ID[N];
int vis[N];
int pre[N];
int NV, NE; // n,m 0-->n-1 0-->m-1
int Minroot;// 求入点
int Directed_MST(int root) { //double
int ret = 0; //double
int i, u, v;
while(true) {
REP(i, NV) In[i] = inf;
REP(i, NE) { //找最小入边
u = E[i].u;
v = E[i].v;
if(E[i].cost < In[v] && u != v) {
In[v] = E[i].cost;
if(u==root) Minroot=i; //求入口
pre[v] = u;
}
}
REP(i, NV) { //如果存在除root以外的孤立点,则不存在最小树形图
if(i == root) continue;
//printf("%.3lf ", In[i]);
if(In[i] == inf) return -1;
}
int cnt = 0;
CL(ID, -1);
CL(vis, -1);
In[root] = 0;
REP(i, NV) { //找环
ret += In[i];
int v = i;
while(vis[v] != i && ID[v] == -1 && v != root) {
vis[v] = i;
v = pre[v];
}
if(v != root && ID[v] == -1) { //重新标号
for(u = pre[v]; u != v; u = pre[u]) {
ID[u] = cnt;
}
ID[v] = cnt++;
}
}
if(cnt == 0) break;
REP(i, NV) {
if(ID[i] == -1) ID[i] = cnt++; //重新标号
}
REP(i, NE) { //更新其他点到环的距离
v = E[i].v;
E[i].u = ID[E[i].u];
E[i].v = ID[E[i].v];
if(E[i].u != E[i].v) {
E[i].cost -= In[v];
}
}
NV = cnt;
root = ID[root];
}
return ret;
}
int main() {
while(scanf("%d%d",&NV,&NE)!=EOF)
{
int x=NE;
for(int i=0;i<NE;i++)
scanf("%d%d%d",&E[i].u,&E[i].v,&E[i].cost);
for(int i=0;i<NV;i++){
E[NE].u=NV;
E[NE].v=i;
E[NE].cost=1e7;
NE++;
}
NV++;
int ans=Directed_MST(NV-1);
ans-=1e7;
if(ans>1e7) printf("impossible\n\n");
else printf("%d %d\n\n",ans,Minroot-x); // Minroot-x 入口
}
}
/*
无固定根的最小树形图
Sample Input
3 1
0 1 1
4 4
0 1 10
0 2 10
1 3 20
2 3 30
Sample Output
impossible
40 0 // 40权值和 0 入口
*/