地址: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;
}