| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
好久没贴代妈了,贴一个,47ms,带注释#include <iostream>
#include <string>
#include <map>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <queue>
using namespace std;
map<string, int> names;//存人名
const int INFTY = (int) 1e9;
int rs = 0;//总人数
int adjNum[25] = {0};//用邻接表存的图
int adjList[25][25] = {0};
int adjDist[25][25] ;
int parkDist[25] = {0};//到park的距离,没有连记为0
int gs[25] = {0};//每个连通分支的顶点个数
int ltfzgs = 0;//连通分支个数
int ltfzbh[25];//每个點所在的连通分支编號
bool used[25] = {0};//是否被使用的标志,通过init()清零
bool cPark[25] = {0};//是否与park直接相连
bool cHx[25][25] = {0};//邻接矩阵存的树图
int dHx[25][25];//邻接矩阵形式的距离
void dfs(int bh){
//dfs得到连通分支
ltfzbh[bh] = ltfzgs;
used[bh] = 1;
for(int i = 0; i < adjNum[bh]; i++){
int next = adjList[bh][i];
if(!used[next]){
dfs(next);
}
}
}
void init(){
//used数组清零
for(int i = 1; i <= rs; i++){
used[i] = 0;
}
}
bool isPark(string &s){
//判断一个地方是不是Park
return !strcmp(s.c_str(), "Park");
}
int getNum(string &s){
//得到一个name对应的人的编號。如果是park返回-1
if(isPark(s)){
return -1;
}
map<string,int>::iterator it = names.find(s);
if(it != names.end()){
return it->second;
}
names.insert(pair<string,int>(s, ++rs));
return rs;
}
int bfs(int bh, int trc[25][25]){
//对bh这个點bfs,求出到park的路径,记录在trc[bh]中
queue<int> bhs;
bool bfsUsed[25] = {0};
bhs.push(bh);
bfsUsed[bh] = 1;
while(!bhs.empty()){
int cur = bhs.front();
bhs.pop();
for(int i = 1; i <= rs; i++){
if(bfsUsed[i] || !cHx[i][cur]) continue;
trc[bh][i] = cur;
if(cPark[i]) return i;
bfsUsed[i] = 1;
bhs.push(i);
}
}
return INFTY;//never happens
}
int main() {
int n;
cin >> n;
while(n--){
//读入,存储数据
string s1, s2;
int d;
cin >> s1 >> s2 >> d;
int a1 = getNum(s1), a2 = getNum(s2);
if(a1 == -1){
parkDist[a2] = d;
}
else if(a2 == -1){
parkDist[a1] = d;
}
else{
adjList[a1][adjNum[a1]] = a2;
adjDist[a1][adjNum[a1]++] = d;
adjList[a2][adjNum[a2]] = a1;
adjDist[a2][adjNum[a2]++] = d;
}
}
int k;
cin >> k;
for(int i = 1; i <= rs; i++){
//求连通分支
if(!used[i]) {
ltfzgs++;
dfs(i);
}
}
for(int i = 1; i <= rs; i++){
//统计连通分支的點数
gs[ltfzbh[i]]++;
}
int zjl = 0;//所求的总距离
for(int ltfz = 1; ltfz <= ltfzgs; ltfz++){
//对每个连通分支作prim
int jrCnt = 0;//已经计入可达集的點数,到该连通分支的总點数就停止
int primDist[25];//Prime算法中的当前距离
int connectTo[25];//与其相连的上一个點
//琐有距离置为INFTY
for(int i = 1; i <= rs; i++){primDist[i] = INFTY;}
init();
for(int i = 1; i <= rs; i++){
//随便找一个點
if(ltfzbh[i] == ltfz){
primDist[i] = 0;
break;
}
}
while(jrCnt < gs[ltfz]){
//Prim的循环,找到最小距离的局外點
int mn = INFTY, arg = -1;
for(int i = 1; i <= rs; i++){
if(!used[i] && primDist[i] < mn){
mn = primDist[i];
arg = i;
}
}
jrCnt++;
if(primDist[arg] != 0){
cHx[arg][connectTo[arg]] = 1;
cHx[connectTo[arg]][arg] = 1;
dHx[connectTo[arg]][arg] = mn;
dHx[arg][connectTo[arg]] = mn;
zjl += mn;
}
used[arg] = 1;
if(jrCnt == gs[ltfz]) break;
//更新其他點的距离
for(int i = 0; i < adjNum[arg]; i++){
int next = adjList[arg][i];
if(used[next]) continue;
int nextDist = adjDist[arg][i];
if(nextDist < primDist[next]){
primDist[next] = nextDist;
connectTo[next] = arg;
}
}
}
}
for(int ltfz = 1; ltfz <= ltfzgs; ltfz++){
//首先对每个连通分支,把到Park最小距離的點和Park相连
int mn = INFTY, arg = -1;
for(int i = 1; i <= rs; i++){
if(ltfzbh[i] == ltfz && parkDist[i] != 0 && parkDist[i] < mn){
mn = parkDist[i];
arg = i;
}
}
cPark[arg] = 1;
zjl += mn;
}
int ds = ltfzgs;//现有的度数
while(ds < k){
//到k就不熊再加了
int mxJ = 0;//最多能减少多少
int argL = -1;//增加的和park直接相连的点
int argQD = -1;//需要去掉的點是argQD和trc[argQD]
int trc[25][25];//追踪上一个点
for(int i = 1; i <= rs; i++){
if(cPark[i] || !parkDist[i]) continue;
int last = bfs(i, trc);//从i到park路径上的最后一个點
int zcbc = 0;//最长的边长
int argB = -1;//记录最长边的前驱點
int cur = last, next = trc[i][last];
while(cur != i){
//找出最长边
int thisDist = dHx[cur][next];
if(thisDist > zcbc){
zcbc = thisDist;
argB = cur;
}
cur = next;
next = trc[i][cur];
}
//更新最长距离
int thisMxJ = zcbc - parkDist[i];
if(thisMxJ > mxJ){
mxJ = thisMxJ;
argL = i;
argQD = argB;
}
}
if(mxJ <= 0){
//没有能减的,退出
break;
}
ds++;
zjl -= mxJ;
//更新图
cPark[argL] = 1;
cHx[argQD][trc[argL][argQD]] = 0;
cHx[trc[argL][argQD]][argQD] = 0;
}
cout << "Total miles driven: " << zjl << endl;
return 0;
}
Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator