一开始觉得是网络流..仔细一看应该是最短路,再看数据范围..呵呵不会写...这道题是最大生成树+最近公共祖先。第一次写..表示各种乱..

因为要求运输货物质量最大,所以路径一定是在最大生成树上的。然后就用LCA求两点之间的能运输的最大重量。预处理O(nlogn),查询O(logn).

----------------------------------------------------------------------------------------

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cctype>
#define rep(i,n) for(int i=0;i<n;i++)
#define clr(x,c) memset(x,c,sizeof(x))
#define Rep(i,l,r) for(int i=l;i<r;i++)
#define addEdge(u,v,d) MST.edges.push_back((Edge){u,v,d})
#define jud(a,b) MST.find(a)-MST.find(b)
using namespace std;
const int maxn=10000+5,maxs=20;
const int inf=0x7fffffff;
struct Edge {
int u,v,d;
Edge(int _u,int _v,int _d):u(_u),v(_v),d(_d) {}
bool operator < (const Edge &x) const {
return d>x.d;
}
};
struct LCA {
int p[maxn][maxs];
int depth[maxn];
int d[maxn][maxs];
bool vis[maxn];
int n;
vector<int> g[maxn];
vector<Edge> edges;
void init(int _n) {
n=_n;
edges.clear();
rep(i,n) { g[i].clear(); vis[i]=false; }
}
void add(int u,int v,int d) {
edges.push_back( (Edge) {u,v,d} );
edges.push_back( (Edge) {v,u,d} );
int m=edges.size();
g[u].push_back(m-2);
g[v].push_back(m-1);
}
void dfs(int x) {
int t=1;
vis[x]=1;
while(depth[x]>=(1<<t)) {
p[x][t]=p[p[x][t-1]][t-1];
d[x][t]=min(d[x][t-1],d[p[x][t-1]][t-1]);
t++;
}
rep(i,g[x].size()) {
Edge &e=edges[g[x][i]];
if(vis[e.v]) continue;
p[e.v][0]=x;
d[e.v][0]=e.d;
depth[e.v]=depth[x]+1;
dfs(e.v);
}
}
void DFS() { rep(i,n) if(!vis[i]) { depth[i]=0; dfs(i); } }
int query(int a,int b) {
int tmp,log=1;
if(depth[a]<depth[b]) swap(a,b);
while((1<<(log+1))<=depth[a]) log++;
int ans=inf;
for(int i=log;i>=0;--i) if(depth[a]-(1<<i)>=depth[b]) {
ans=min(ans,d[a][i]);
a=p[a][i];
}
if(a==b) return ans;
for(int i=log;i>=0;--i) if(p[a][i]!=-1 && p[a][i]!=p[b][i]) {
ans=min(ans,d[a][i]); a=p[a][i];
ans=min(ans,d[b][i]); b=p[b][i];
}
return ans=min(ans,min(d[a][0],d[b][0]));
}
};
LCA lca;
  
struct KRUSKAL {
int n;
int p[maxn];
vector<Edge> edges;
void init(int _n) {
n=_n;
edges.clear();
}
int find(int x) { return x==p[x] ? x : p[x]=find(p[x]); }
void kruskal() {
rep(i,n) p[i]=i;
sort(edges.begin(),edges.end());
rep(i,edges.size()) {
Edge &e=edges[i];
int x=find(e.u),y=find(e.v);
if(x!=y) {
p[x]=y;
   lca.add(e.u,e.v,e.d);
}
}
}
};
  
KRUSKAL MST;
int read() {
char c=getchar();
int ans=0,f=1;
while(!isdigit(c)) { if(c=='-') f=-1; c=getchar(); }
while(isdigit(c)) { (ans*=10)+=c-'0'; c=getchar(); }
return f*ans;
}
   
int main()
{
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
int n=read(),m=read();
MST.init(n);
lca.init(n);
rep(i,m) {
int u=read(),v=read(),d=read();
addEdge(--u,--v,d);
}
MST.kruskal();
lca.DFS();
n=read();
rep(i,n) {
int a=read(),b=read();
--a; --b;
if(jud(a,b)) printf("-1\n");
else {
printf("%d\n",lca.query(a,b));
}
}
return 0;
}

----------------------------------------------------------------------------------------

3287 货车运输

2013年NOIP全国联赛提高组

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 钻石 Diamond

最新文章

  1. Life Is A Funny Proposition After All
  2. php代码美化/格式化 还原 -问题
  3. android-数据存储之外部file存储(sdcard)
  4. Can &#39;t connect to local MySQL server through socket &#39;/var/lib/mysql/mysql.sock &#39;(2) ;
  5. 在Windows Live Writer中插入C# code
  6. JavaScript Replace 多个字符
  7. 条件放在left join后面和where后面
  8. ssh 无密码登录远程服务器
  9. 在MDK中怎样生成*.bin格式的文件?
  10. javascript深入理解js闭包(看了挺多的,感觉这篇比较透彻)
  11. 纯Jquery前端分页
  12. CSS,浮动及其影响
  13. Java面向对象和高级特性 项目实战(一)
  14. Comparator与Comparable,自定义排序和类比较器,TreeSet对象排序
  15. pm2管理node
  16. Vscode的python配置(macOS)
  17. free命令详解
  18. ubuntu下安装nginx1.11.10
  19. ios 关于屏幕旋转和屏幕晃动
  20. @Resource,@Autowired,@Inject3种注入方式

热门文章

  1. Unix/Linux环境C编程入门教程(13) 开发环境搭建VMware软件安装
  2. 加入收藏夹的js代码(求兼容chrome浏览器的代码)
  3. iOS开发基本须要
  4. hdu 2102 A计划(双层BFS)(具体解释)
  5. 脚本化css
  6. DataSet和DataTable详解
  7. .Net平台-MVP模式再探(二)
  8. BZOJ 2245: [SDOI2011]工作安排( 费用流 )
  9. Class类对象的三种实例化方法
  10. 一周学会Mootools 1.4中文教程:(6)动画