地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3016
题意:给你n条线段,这些线段都平行于坐标轴,没有线段重叠,但是有交点,切割每条线段有一个值,现在这些线段形成一些封闭的区间,问怎样切割使得所有点之间有通路,且花费最小
分析:这题抛掉线段的外壳,很容易发现每个格子是一个点,外面的平面是一个点,点之间的边正好是切割线段的花费,答案明显的是最小生成树的值。。。不过这些线段怎么处理成小格子,头疼= =,一开始想放弃,不过仔细一想,好像可以做,大格子不好处理,那就处理最小的格子啊,把坐标离散化,然后做成n×m个格子,格子之间的边如果是一条线段,那么值就是切割线段的值,如果没有线段,那么值为零,现在建边就简单了,只要建每个格子上下左右的边就行。。。然后就呵呵了,具体看代码~ ~
代码:
/** head files*/ #include <cstdlib> #include <cctype> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <cassert> #include <vector> #include <string> #include <iostream> #include <sstream> #include <map> #include <set> #include <queue> #include <stack> #include <fstream> #include <numeric> #include <iomanip> #include <bitset> #include <list> #include <stdexcept> #include <functional> #include <utility> #include <ctime> using namespace std; /** some operate*/ #define REP(i,n) for(int i=0;i<(n);++i) #define FOR(i,l,h) for(int i=(l);i<=(h);++i) #define DWN(i,h,l) for(int i=(h);i>=(l);--i) #define foreach(e,x) for(__typeof(x.begin()) e=x.begin();e!=x.end();++e) #define CLR(arr) memset(arr,0,sizeof(arr)) #define MAX3(a,b,c) max(a,max(b,c)) #define MAX4(a,b,c,d) max(max(a,b),max(c,d)) #define MIN3(a,b,c) min(a,min(b,c)) #define MIN4(a,b,c,d) min(min(a,b),min(c,d)) /** some const*/ #define N 1210 #define M N*N #define PI acos(-1.0) #define oo 1000000000 #define loo 1000000000000000000LL #define eps 1e-8 /** some alias*/ typedef long long LL; int dx[]={0,0,-1,1}; int dy[]={-1,1,0,0}; /** Global variables*/ /** some template names, just push ctrl+j to get it in*/ //getint 读入优化 //manacher 求最长回文子串 //pqueue 优先队列 //combk n元素序列的第m小的组合和 //pmatrix n个点的最大子矩阵 //suffixarray 后缀数组 //sbtree 平衡树 struct seg { int x1,y1,x2,y2,c; void rd() { scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&c); } }; struct Node { int v,c; Node(){} Node(int v, int c):v(v),c(c){} bool operator<(const Node &a)const { return c>a.c; } }; vector<int> gx; vector<int> gy; seg sg[N]; int g[N][N]; vector<Node> e[M]; bool vis[M]; priority_queue<Node> pq; int no(int i, int j) { return g[i*2][j*2]; } void addedge(int u, int v, int c) { e[u].push_back(Node(v,c)); e[v].push_back(Node(u,c)); } LL solve() { while(!pq.empty())pq.pop(); LL ret=0; for(pq.push(Node(0,0));!pq.empty();) { Node now=pq.top(); pq.pop(); if(vis[now.v])continue; ret=ret+now.c; foreach(it,e[now.v]) if(!vis[it->v])pq.push(*it); vis[now.v]=1; } return ret; } int main() { freopen("a","r",stdin); //freopen("wa","w",stdout); int n,m,t; scanf("%d",&t); while(t--) { scanf("%d",&n); gx.clear(); gy.clear(); REP(i,n) { sg[i].rd(); gx.push_back(sg[i].x1); gx.push_back(sg[i].x2); gy.push_back(sg[i].y1); gy.push_back(sg[i].y2); if(sg[i].x1>sg[i].x2)swap(sg[i].x1,sg[i].x2); if(sg[i].y1>sg[i].y2)swap(sg[i].y1,sg[i].y2); } sort(gx.begin(),gx.end()); sort(gy.begin(),gy.end()); gx.resize(unique(gx.begin(),gx.end())-gx.begin()); gy.resize(unique(gy.begin(),gy.end())-gy.begin()); CLR(g); unsigned xi,yi; REP(i,n) { xi=lower_bound(gx.begin(),gx.end(),sg[i].x1)-gx.begin(); yi=lower_bound(gy.begin(),gy.end(),sg[i].y1)-gy.begin(); if(sg[i].x1<sg[i].x2) { for(xi++;xi<gx.size();xi++) { if(gx[xi]>sg[i].x2)break; g[xi*2][yi*2+1]=sg[i].c; } } else if(sg[i].y1<sg[i].y2) { for(yi++;yi<gy.size();yi++) { if(gy[yi]>sg[i].y2)break; g[xi*2+1][yi*2]=sg[i].c; } } } m=0; for(xi=1;xi<gx.size();++xi) for(yi=1;yi<gy.size();++yi) { g[xi*2][yi*2]=++m; e[m].clear(); vis[m]=0; } e[0].clear(); vis[0]=0; for(xi=0;xi<gx.size();++xi) for(yi=0;yi<gy.size();++yi) { if(no(xi+1,yi)!=no(xi,yi)) addedge(no(xi,yi),no(xi+1,yi),g[xi*2+1][yi*2]); if(no(xi,yi+1)!=no(xi,yi)) addedge(no(xi,yi),no(xi,yi+1),g[xi*2][yi*2+1]); } printf("%lld\n",solve()); } return 0; }