标签:
每组数据第一行是两个整数N、M(N<=100,M<=10000),
N表示成都的大街上有几个路口,
标号为1的路口是商店所在地,标号为N的路口是赛场所在地,
M则表示在成都有几条路。
N=M=0表示输入结束。
接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。
输入保证至少存在1条商店到赛场的路线。
Output
对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间
Sample Input
N(有几个路口) M(有几条路)
nodenum edgenum
2 1
1 2 3
3 3
1 2 5
2 3 5
3 1 2
0 0
Sample Output
3
2
SPFA版本:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<climits>
#include<queue>
#include<algorithm>
using namespace std;
#define N 110
#define MAX INT_MAX >> 1
#define CLR(arr, what) memset(arr, what,sizeof(arr))
int nodenum, edgenum;
int map[N][N], dis[N];
bool visit[N];
int SPFA(int src, int des)
{
queue<int> q;
CLR(visit, false);
for(int i = 1;i <= nodenum; ++i)
dis[i] = MAX;
dis[src] = 0;
visit[src] = true;
q.push(src);
while(!q.empty())
{
int cur = q.front();
q.pop();
visit[cur] = false; //出队标记为false
for(int i = 1; i <= nodenum; ++i)
{
if(dis[i] > dis[cur] + map[cur][i]) //没有2个集合,和Dijkstra有本质区别
{
dis[i] = dis[cur] +map[cur][i]; //能松弛就松弛
if(!visit[i]) //不在队列中则加入,然后更新所有以前经过此点的最短路径
{
q.push(i);
visit[i] = true;
}
}
}
}
return dis[des];
}
int main()
{
intstart, end, cost;
intanswer;
while(~scanf("%d%d", &nodenum, &edgenum) &&(nodenum + edgenum))
{
for(int i = 1; i <= nodenum; ++i)
for(int j = 1; j <= nodenum; ++j)
map[i][j] = MAX;
for(int i = 0; i < edgenum; ++i)
{
scanf("%d%d%d", &start, &end, &cost);
if(cost < map[start][end])
map[start][end] =map[end][start] = cost;
}
answer = SPFA(1, nodenum);
printf("%d\n", answer);
}
return 0;
}
布线问题:由于安全问题,只能选择一个楼连接到外界供电设备。
引水工程:它们可以自建水库解决缺水问题
/*
1
V e
4 6
1 2 10
2 3 10
3 1 10
1 4 1
2 4 1
3 4 1
1 3 5 6
*/
#include<iostream>
using namespace std;
#define MAX 505
#define MAXCOST 0x7fffffff
int graph[MAX][MAX];
int prim(int graph[][MAX], int n)
{
intlowcost[MAX];
intmst[MAX];
inti, j, min, minid, sum = 0;
for(i = 2; i <= n; i++)
{
lowcost[i]= graph[1][i];
mst[i]= 1;
}
mst[1]= 0;
for(i = 2; i <= n; i++)
{
min= MAXCOST;
minid= 0;
for(j = 2; j <= n; j++)
{
if(lowcost[j] < min && lowcost[j] != 0)
{
min= lowcost[j];
minid= j;
}
}
//cout<< "V" << mst[minid] << "-V" <<minid << "=" << min << endl;
sum+= min;
lowcost[minid]= 0;
for(j = 2; j <= n; j++)
{
if(graph[minid][j] < lowcost[j])
{
lowcost[j]= graph[minid][j];
mst[j]= minid;
}
}
}
returnsum;
}
int main()
{
inti, j, k, m, n;
intx, y, cost;
intzushu;
cin>>zushu;
while(zushu--)
{
cin >> m >> n;//m=顶点的个数,n=边的个数
for(i = 1; i <= m; i++)
{
for(j = 1; j <= m; j++)
{
graph[i][j]= MAXCOST;
}
}
for(k = 1; k <= n; k++)
{
cin>> i >> j >> cost;
graph[i][j]= cost;
graph[j][i]= cost;
}
cost = prim(graph, m);
int min_v=MAXCOST;
for(inti=1;i<=m;++i)
{
intt;
cin>>t;
if(t<min_v)
min_v=t;
}
cout <<cost+min_v<< endl;
}
return0;
}
-----------------------------------------------------------
/*
得到的统计表中列出了任意两村庄间的距离
3
1 2 1
1 3 2
2 3 4
4
1 2 1
1 3 4
1 4 1
2 3 3
2 4 2
3 4 5
0
*/
#include<iostream>
#include<cstdio>
using namespace std;
#define MAX 505
#define MAXCOST 0x7fffffff
int graph[MAX][MAX];
int prim(int graph[][MAX], int n)
{
intlowcost[MAX];
intmst[MAX];
inti, j, min, minid, sum = 0;
for(i = 2; i <= n; i++)
{
lowcost[i]= graph[1][i];
mst[i]= 1;
}
mst[1]= 0;
for(i = 2; i <= n; i++)
{
min= MAXCOST;
minid= 0;
for(j = 2; j <= n; j++)
{
if(lowcost[j] < min && lowcost[j] != 0)
{
min= lowcost[j];
minid= j;
}
}
//cout<< "V" << mst[minid] << "-V" <<minid << "=" << min << endl;
sum+= min;
lowcost[minid]= 0;
for(j = 2; j <= n; j++)
{
if(graph[minid][j] < lowcost[j])
{
lowcost[j]= graph[minid][j];
mst[j]= minid;
}
}
}
returnsum;
}
int main()
{
inti, j, k, m, n;
intx, y, cost;
while(scanf("%d",&m),m)
{
//cin >> m >> n;//m=顶点的个数,n=边的个数
n=(m*(m-1))/2;
for(i = 1; i <= m; i++)
{
for(j = 1; j <= m; j++)
{
graph[i][j]= MAXCOST;
}
}
for(k = 1; k <= n; k++)
{
cin>> i >> j >> cost;
graph[i][j]= cost;
graph[j][i]= cost;
}
cost = prim(graph, m);
cout <<cost<< endl;
}
return0;
}
/*
1
3(3*3的矩阵)
0 990 692
990 0 179
692 179 0
*/
#include "stdio.h"
#include "string.h"
#define N 500
#define INT 10000
bool vis[N];
int dis[N];
int a[N][N];
int main(){
intt;
scanf("%d",&t);
while(t--){
intn;
scanf("%d",&n);
inti,j,temp,k;
memset(vis,0,sizeof(vis));
for(i=1;i<=n;++i){
for(j=1;j<=n;++j){
scanf("%d",&a[i][j]);
}
}
for(i=1;i<=n;++i){
dis[i]=INT;
}
dis[1]=0;
for(i=1;i<=n;++i){
temp=INT;
k=0;
for(j=1;j<=n;++j){
if(!vis[j]&&dis[j]<temp){
temp=dis[j];
k=j;
}
}
vis[k]=1;
for(j=1;j<=n;++j){
if(!vis[j]&&dis[j]>a[k][j]){
dis[j]=a[k][j];
}
}
}
intmax=0;
for(i=1;i<=n;++i){
if(max<dis[i])
max=dis[i];
}
printf("%d\n",max);
}
return0;
}
4
0 4 9 21
4 0 8 17
9 8 0 16
21 17 16 0
#include <stdio.h>
#include <string.h>
#define MaxInt 0x3f3f3f3f
#define N 110
int map[N][N],low[N],visited[N];
int n;
int prim()
{
inti,j,pos,min,result=0;
memset(visited,0,sizeof(visited));
visited[1]=1;pos=1;
for(i=1;i<=n;i++)
if(i!=pos) low[i]=map[pos][i];
for(i=1;i<n;i++)
{
min=MaxInt;
for(j=1;j<=n;j++)
if(visited[j]==0&&min>low[j])
{
min=low[j];pos=j;
}
result+=min;
visited[pos]=1;
//更新权值
for(j=1;j<=n;j++)
if(visited[j]==0&&low[j]>map[pos][j])
low[j]=map[pos][j];
}
return result;
}
int main()
{
inti,v,j,ans;
while(scanf("%d",&n)!=EOF)
{
memset(map,MaxInt,sizeof(map));
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
scanf("%d",&v);
map[i][j]=map[i][j]=v;
}
ans=prim();
printf("%d\n",ans);
}
return 0;
}
1
3
0 990 692
990 0 179
692 179 0
692
#include<stdio.h>
#define MAX 505
#define inf 999999
int c[MAX][MAX];
int n;
void prim()
{
intlowcost[MAX ];
intclosest[MAX ];
bool s[MAX ];
s[1]=true;
for(int i=2;i<=n;i++)
{
lowcost[i]=c[1][i];
closest[i]=1;
s[i]=false;
}
for(int i=1;i<=n;i++)
{
int min=inf;
int j=i;
for(int k=2;k<=n;k++)
if((lowcost[k]<min)&&(!s[k]))
{
min=lowcost[k];
j=k;
}
//cout<<j<<" "<<closet[j]<<endl;输出最小生成树的路径。
s[j]=true;
for(int k=2;k<=n;k++)
{
if((c[j][k]<lowcost[k])&&(!s[k]))
{
lowcost[k]=c[j][k];
closest[k]=j;
}
}
}
//最小生成树的边值已经放大lowcost数组中了。遍历一下就可以得到最大最小值。
intresult=-1;
for(int i=2;i<=n;i++)
{
if(result<lowcost[i])
result=lowcost[i];
}
printf("%d\n",result);
}
int main()
{
intt;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%d",&c[i][j]);
}
}
prim();
}
return 0;
}
/*1
5
0 5 44 3 6
5 0 22 2 2
4 2 0 3 3 3
4 2 3 0 4 5
3 2 3 4 0 1
5 2 3 5 1 0*/
#include <stdio.h>
#include <string.h>
#define MaxInt 0x3f3f3f3f
#define N 303
int map[N][N],low[N],visited[N];
int n;
int prim()
{
inti,j,pos,min,result=0;
memset(visited,0,sizeof(visited));
visited[1]=1;pos=1;
for(i=1;i<=n;i++)
if(i!=pos) low[i]=map[pos][i];
for(i=1;i<n;i++)
{
min=MaxInt;
for(j=1;j<=n;j++)
if(visited[j]==0&&min>low[j])
{
min=low[j];
pos=j;
}
result+=min;
visited[pos]=1;
for(j=1;j<=n;j++)
if(visited[j]==0&&low[j]>map[pos][j])
low[j]=map[pos][j];
}
return result;
}
int main()
{
inti,v,j,ans,zushu;
scanf("%d",&zushu);
inta[303];
while(zushu--)
{
scanf("%d",&n);
memset(map,MaxInt,sizeof(map));
map[1][1]=0;
for(i=2;i<=n+1;++i)
{
scanf("%d",&map[i][1]);
map[1][i]=map[i][1];
}
getchar();
for(i=2;i<=n+1;i++)
for(j=2;j<=n+1;j++)
{
scanf("%d",&v);
map[i][j]=map[i][j]=v;
}
n=n+1;
ans=prim();
printf("%d\n",ans);
}
return 0;
}
省政府“畅通工程”的目标是
使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。
现请你编写程序,计算出全省畅通需要的最低成本。
Input
测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M ( < 100 );随后的 N
行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。
为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。
Output
对每个测试用例,在1行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出“?”。
Sample Input
3 3
1 2 1
1 3 2
2 3 4
1 3
2 3 2
0 100
Sample Output
3
?
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAX 100
int father[MAX], son[MAX];
int v, l;
typedef struct Kruskal //存储边的信息
{
inta;
intb;
intvalue;
};
bool cmp(const Kruskal & a, const Kruskal& b)
{
returna.value < b.value;
}
int unionsearch(int x) //查找根结点+路径压缩
{
returnx == father[x] ? x : unionsearch(father[x]);
}
bool join(int x, int y) //合并
{
introot1, root2;
root1= unionsearch(x);
root2= unionsearch(y);
if(root1== root2) //为环
returnfalse;
elseif(son[root1] >= son[root2])
{
father[root2]= root1;
son[root1]+= son[root2];
}
else
{
father[root1]= root2;
son[root2]+= son[root1];
}
returntrue;
}
int main()
{
intltotal, sum, flag;
Kruskaledge[MAX];
//scanf("%d",&ncase);
while(scanf("%d%d",&l, &v),l)
{
ltotal= 0, sum = 0, flag = 0;
for(inti = 1; i <= v; ++i) //初始化
{
father[i]= i;
son[i] = 1;
}
for(inti = 1; i <= l ; ++i)
{
scanf("%d%d%d",&edge[i].a, &edge[i].b, &edge[i].value);
}
sort(edge+ 1, edge + 1 + l, cmp); //按权值由小到大排序
intcount=0;
for(inti = 1; i <= l; ++i)
{
if(join(edge[i].a,edge[i].b))
{
ltotal++;//边数加1
sum+= edge[i].value; //记录权值之和
//cout<<edge[i].a<<"->"<<edge[i].b<<endl;
}
if(ltotal== v - 1) //最小生成树条件:边数=顶点数-1
{
flag= 1;
break;
}
count++;
}
//printf("count%d\n", count);
if(flag)
printf("%d\n",sum);
else
printf("?\n");
}
return0;
}
/*
目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,
只要互相间接通过道路可达即可)。问最少还需要建设多少条道路?
v e
4 2
1 3
4 3
3 3
1 2
1 3
2 3
5 2
1 2
3 5
999 0
0
输出最少还需要建设的道路数目。
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int pre[1010];
int unionsearch(int root) //查找父节点+路径压缩(非递归)
{
intson, tmp;
son= root;
while(root != pre[root])
root = pre[root];
while(son != root)
{
tmp = pre[son];
pre[son] = root;
son = tmp;
}
return root;
}
/*int unionsearch(int root) //查找父节点+路径压缩(递归)
{
returnroot == pre[root] ? root : unionsearch(pre[root]);
}*/
int main()
{
intnum, road, total, i, start, end, root1, root2;
while(scanf("%d%d", &num, &road) && num)
{
total = num - 1;
for(i = 1; i <= num; ++i)
pre[i] = i;
while(road--)
{
scanf("%d%d", &start, &end);
root1 = unionsearch(start);
root2 = unionsearch(end);
if(root1 != root2)
{
pre[root1] = root2;
total--;
}
}
printf("%d\n", total);
}
return 0;
}
/*
对每个测试用例,在 1 行里输出全省畅通需要的最低成本。
若统计数据不足以保证畅通,则输出 No solution。
2
e v
3 3
1 2 1
1 3 2
2 3 4
1 3
2 3 2
样例输出
3
No solution
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
//判断是否畅通
int pre[1010];
int unionsearch(int root) //查找父节点+路径压缩(非递归)
{
intson, tmp;
son= root;
while(root != pre[root])
root = pre[root];
while(son != root)
{
tmp = pre[son];
pre[son] = root;
son = tmp;
}
return root;
}
//最小生成树
#define MAX 505
#define MAXCOST 0x7fffffff
int graph[MAX][MAX];
int prim(int graph[][MAX], int n)
{
intlowcost[MAX];
intmst[MAX];
inti, j, min, minid, sum = 0;
for(i = 2; i <= n; i++)
{
lowcost[i]= graph[1][i];
mst[i]= 1;
}
mst[1]= 0;
for(i = 2; i <= n; i++)
{
min= MAXCOST;
minid= 0;
for(j = 2; j <= n; j++)
{
if(lowcost[j] < min && lowcost[j] != 0)
{
min= lowcost[j];
minid= j;
}
}
//cout<< "V" << mst[minid] << "-V" <<minid << "=" << min << endl;
sum+= min;
lowcost[minid]= 0;
for(j = 2; j <= n; j++)
{
if(graph[minid][j] < lowcost[j])
{
lowcost[j]= graph[minid][j];
mst[j]= minid;
}
}
}
returnsum;
}
int main()
{
intnum, road, total, start, end, root1, root2;
inti, j, k, m, n;
intx, y, cost;
intzushu;
cin>>zushu;
while(zushu--)
{
cin >> n >> m ;//m=顶点的个数,n=边的个数
num=m,road=n;
for(i = 1; i <= m; i++)
{
for(j = 1; j <= m; j++)
{
graph[i][j]= MAXCOST;
}
}
//------------判断是否畅通
//num顶点,road道路
total = num - 1;
for(i = 1; i <= num; ++i)
pre[i] = i;
for(k = 1; k <= n; k++)
{
cin>> i >> j >> cost;
graph[i][j]= cost;
graph[j][i]= cost;
start=i;
end=j;
root1= unionsearch(start);
root2 = unionsearch(end);
if(root1 != root2)
{
pre[root1] = root2;
total--;
}
}
//cout<<total<<endl;
if(total<1)
{
cost = prim(graph, m);
printf("%d\n",cost);
}
else{
printf("Nosolution\n");
}
}
return 0;
}
/*
2
v e
4 3
1 2
1 3
1 4
一笔画就yes,不一笔画no
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <climits>
#include <algorithm>
#include <cmath>
#define LL long long
using namespace std;
vector<int>e[1010];
int deg[1010];
bool vis[1010];
void dfs(int u) {
vis[u] = true;
for(int i = 0; i < e[u].size(); i++) {
if(!vis[e[u][i]]) {
dfs(e[u][i]);
}
}
}
int main() {
intkase,p,q,i,u,v,temp;
bool flag;
scanf("%d",&kase);
while(kase--) {
scanf("%d %d",&p,&q);
memset(deg,0,sizeof(deg));
memset(vis,false,sizeof(vis));
for(i = 0; i < 1010; i++)
e[i].clear();
for(i = 0; i < q; i++) {
scanf("%d %d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
deg[u]++;
deg[v]++;
}
dfs(1);
flag = true;
for(i = 1; i <= p; i++)
if(!vis[i]) {
flag = false;
break;
}
if(flag) {
for(temp = 0,i = 1; i <= p; i++) {
if(deg[i]&1) {
temp++;
if(temp > 2) break;
}
}
}
if(!flag || temp > 2) puts("No");
else puts("Yes");
}
return 0;
}
-------------------------------------------------
/*
1
3(3男3女) 4(可能关系)
(男 女)
1 1
1 3
2 2
3 2
*/
#include<cstdio>
#include<cstring>
using namespace std;
#define N 10010
#define M 510
int head[M], next[N], key[N], num;
int match[M];
bool use[M];
void add(int u, int v) //hash表存图
{
key[num]= v;
next[num]= head[u];
head[u]= num++;
}
bool find(int u) //匈牙利算法
{
inttemp;
for(inti = head[u]; i != -1; i = next[i])
{
temp= key[i];
if(!use[temp])
{
use[temp]= true;
if(match[temp]== -1 || find(match[temp])) //增广路
{
match[temp]= u;
returntrue;
}
}
}
returnfalse;
}
int sum(int n) //最大匹配数
{
intsumall = 0;
for(inti = 1; i <= n; ++i)
{
memset(use,false, sizeof(use));
if(find(i))
sumall++;
}
returnsumall;
}
int main()
{
intncase;
intallnum, relation;
intu, v;
scanf("%d",&ncase);
while(ncase--)
{
num= 0;
memset(head,-1, sizeof(head));
memset(match,-1, sizeof(match));
scanf("%d%d",&allnum, &relation);
for(inti = 0; i < relation; ++i)
{
scanf("%d%d",&u, &v);
add(u,v);
}
printf("%d\n",sum(allnum));
}
return0;
}
2.0-1背包
-------------------------------------------------------------------------------------------------------
/*
描述
ctest有n个苹果,要将它放入容量为v的背包。给出第i个苹果的大小和价钱,求出能放入背包的苹果的总价钱最大值。
输入有多组测试数据,每组测试数据第一行为2个正整数,分别代表苹果的个数n和背包的容量v,n、v同时为0时结束测试,
此时不输出。接下来的n行,每行2个正整数,用空格隔开,分别代表苹果的大小c和价钱w。所有输入数字的范围大于等于0,
小于等于1000。输出对每组测试数据输出一个整数,代表能放入背包的苹果的总价值。样例输入
3 3
1 1
2 1
3 1
0 0
样例输出2
来源动态规划经典问题上传者ctest*/
//经典的算法
#include<stdio.h>
#include<string.h>
intmax(int k,int m)
{return m>k?m:k;}
intc[1001],w[1001],dp[1010][1010];
main()
{
intn,v;
while(scanf("%d %d",&n,&v),n&&v)
{
memset(dp,0,sizof(dp));//此函数包含在string头文件里
for(int i=1;i<n;i++)
scanf("%d %d",&c[i],&w[i]);
for(int i=1;i<=n;i++)
for(int j=1;j<=v;j++)
{
if(j<c[i]) dp[i][j]=dp[i-1][j];
else dp[i][j]=max(dp[i-1][j],dp[i-1][j-c[i]]+w[i]);
}
printf("%d\n",dp[n][v]);
}
}
//改进的算法
#include<stdio.h>
#include<string.h>
intmax(int k,int m)
{return k>m?k:m;}
intdp[1010];
main()
{
intn,v,i,j;
while(scanf("%d%d",&n,&v),n&&v)
{
memset(dp,0,sizeof(dp));//此函数包含在string头文件里
intc,w;
for(i=1;i<=n;i++)
{
scanf("%d%d",&c,&w);
for(j=v;j>=c;j--)
{
dp[j]=max((dp[j-c]+w),dp[j]);
}
}
printf("%d\n",dp[v]);
}
}
-
/*
input:
5 2
1 2 3 4 5
1 3
2 4
output:
6
9
*/
#include<iostream>
#include<cstdio>
using namespace std;
int C[1000006];//保存树状数组
int n;//元素个数(即节点个数),下标从1开始
//求最小幂2的k次幂
int lowbit(int t){ return t&(t^(t-1)); }
//求前n项和
int sum(int end)
{
intsum=0;
while(end>0)
{
sum+=C[end];
end-=lowbit(end);//或也可end^=Lowbit(end);
}
returnsum;
}
//对某个元素进行加减法操作
voidPlus(int pos,int num)
{
while(pos<=n)
{
C[pos]+=num;
pos+=lowbit(pos);
}
}
int main()
{
intzishu,i;
scanf("%d%d",&n,&zishu);
for(i=1;i<=n;++i)
{
inttemp;
scanf("%d",&temp);//输入原始序列的第i个元素
Plus(i,temp);//第i个元素在原来为零的基础上加上temp
}
while(zishu--)
{
intmin,max;
scanf("%d%d",&min,&max);
printf("%d\n",sum(max)-sum(min-1));
}
return0;
}
---------------------------------------------------------------------------------------------------------------------------------------------------
/*
问题一:给你N个数和M次操作,操作分两种——
1,U a b 第a个数增加b;2,S a b 求区间[a, b]的和。
input:
5 6
1 2 3 4 5
QUERY 1 3
ADD 1 2
QUERY 1 3
ADD 2 3
QUERY 1 2
QUERY 1 5
*/
#include<iostream>
#include<cstdio>
using namespace std;
int C[1000006];//保存树状数组
int n;//元素个数(即节点个数),下标从1开始
//求最小幂2的k次幂
int lowbit(int t){ return t&(t^(t-1)); }
//求前n项和
int sum(int end)
{
intsum=0;
while(end>0)
{
sum+=C[end];
end-=lowbit(end);//或也可end^=Lowbit(end);
}
returnsum;
}
//对某个元素进行加减法操作
voidPlus(int pos,int num)
{
while(pos<=n)
{
C[pos]+=num;
pos+=lowbit(pos);
}
}
int main()
{
intzishu,i;
scanf("%d%d",&n,&zishu);
for(i=1;i<=n;++i)
{
inttemp;
scanf("%d",&temp);//输入原始序列的第i个元素
Plus(i,temp);//第i个元素在原来为零的基础上加上temp
}
while(zishu--)
{
intmin,max;
charch[10];
scanf("%s%d %d",ch,&min,&max);
if(ch[0]==‘Q‘)
printf("%d\n",sum(max)-sum(min-1));
else
Plus(min,max);
}
return0;
}
--------------------------------------------------------------------------------------------------------------
3、/*
那么我们用sum[n]代表前n项和,s[n]代表前n个sum和
ans = m*sum[i]-(s[i-1]-s[i-1-m])
*/
#include <stdio.h>
#include <algorithm>
using namespace std;
int sum[1000005],s[1000005];
int main()
{
intn,m,a,i,j,k;
while(~scanf("%d%d",&n,&m))
{
sum[0] = s[0] = 0;
for(i = 1;i<=n;i++)
{
scanf("%d",&a);
sum[i] = sum[i-1]+a;
s[i] = s[i-1]+sum[i];
}
if(n<=m)
{
printf("%d\n",sum[n]);//?
continue;
}
int ans = 0,maxn = 0;
for(i = m;i<=n;i++)
{
ans = m*sum[i]-(s[i-1]-s[i-1-m]);//?
maxn = max(maxn,ans);
}
printf("%d\n",maxn);
}
return 0;
}
-------------------------------------树状数组------------------------------------------------------------------
#include <stdio.h>
#include <string.h>
#define MaxInt 0x3f3f3f3f
#define N 110
//创建map二维数组储存图表,low数组记录每2个点间最小权值,visited数组标记某点是否已访问
int map[N][N],low[N],visited[N];
int n;
int prim()
{
/*
4
04 9 21
40 8 17
98 0 16
2117 16 0
*/
inti,j,pos,min,result=0;
memset(visited,0,sizeof(visited));
//从某点开始,分别标记和记录该点
//从一开始,标记一下给位置,并且记录了他的位置。
visited[1]=1;pos=1;
//第一次给low数组赋值
for(i=1;i<=n;i++)
if(i!=pos)
low[i]=map[pos][i];
//low[1]=0(这个元素直接跳过),low[2]=4,low[3]=9,low[4]=21
//再运行n-1次
for(i=1;i<n;i++)
{
//找出最小权值并记录位置
min=MaxInt;
for(j=1;j<=n;j++)
{ //第一次执行前已经,visited[1]=1
//j=1, visited[1]=1
//j=2,visited[2]=0,min=maxint,low[2]=4, min=4,pos=2;
//j=3,visited[3]=0,low[3]=9, bi
if(visited[j]==0&&min>low[j])
{
min=low[j];
pos=j;
}
}
//最小权值累加
result+=min;
//标记该点
visited[pos]=1;
//更新权值
for(j=1;j<=n;j++)
{
if(visited[j]==0&&low[j]>map[pos][j])
low[j]=map[pos][j];
}
}
return result;
}
int main()
{
int i,v,j,ans;
n=4;
memset(map,MaxInt,sizeof(map));
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
scanf("%d",&v);
map[i][j]=map[i][j]=v;
}
ans=prim();
return 0;
}
修路方案
时间限制:3000 ms | 内存限制:65535 KB
难度:5
描述
南将军率领着许多部队,它们分别驻扎在N个不同的城市里,这些城市分别编号1~N,由于交通不太便利,南将军准备修路。
现在已经知道哪些城市之间可以修路,如果修路,花费是多少。
现在,军师小工已经找到了一种修路的方案,能够使各个城市都联通起来,而且花费最少。
但是,南将军说,这个修路方案所拼成的图案很不吉利,想让小工计算一下是否存在另外一种方案花费和刚才的方案一样,现在你来帮小工写一个程序算一下吧。
输入
第一行输入一个整数T(1<T<20),表示测试数据的组数
每组测试数据的第一行是两个整数V,E,(3<V<500,10<E<200000)分别表示城市的个数和城市之间路的条数。数据保证所有的城市都有路相连。
随后的E行,每行有三个数字A B L,表示A号城市与B号城市之间修路花费为L。
输出
对于每组测试数据输出Yes或No(如果存在两种以上的最小花费方案则输出Yes,如果最小花费的方案只有一种,则输出No)
样例输入
2
3 3
1 2 1
2 3 2
3 1 3
4 4
1 2 2
2 3 2
3 4 2
4 1 2
样例输出
No
Yes
方法一:
#include<iostream>
#include<stdio.h>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
#define MaxV 510
#define MaxE 200005
struct Edge
{
intx,y,dis;
};
Edge edge[MaxE],edge1[MaxE]; //分别是边数组 最小生成树中的边数组
int father[MaxV],Num[MaxV],num,dex,dey; //并查集 num统计生成树边的条数 dex dey指枚举删除边的x,y坐标
void Init(int V) //并查集初始化,单个元素自成集合
{
for(int i=1;i<=V;i++)
{
father[i]=i;
Num[i]=1;
}
}
int findfather(int x) //寻找父结点,可以压缩路径。。
{
for(x;x!=father[x];x=father[x]) ;
returnfather[x];
}
void Union(int x,int y)
{
intt1,t2;
t1=findfather(x);
t2=findfather(y);
if(Num[t1]>Num[t2])
{
father[t2]=t1;
Num[t1]+=Num[t2];
}
else
{
father[t1]=t2;
Num[t2]+=Num[t1];
}
}
int comp(const void* p1,const void* p2)
{
return(*(Edge*)p1).dis>(*(Edge*)p2).dis;
}
int Krusual(int V,int E)
{
intsum=0;
for(int i=1;i<=E;i++)
{
if(findfather(edge[i].x)!=findfather(edge[i].y))
{
sum+=edge[i].dis;
Union(edge[i].x,edge[i].y);
edge1[++num]=edge[i];
}
}
returnsum;
}
int AKrusual(int V,int E)
{
Init(V);
intsum=0;
qsort(edge+1,E,sizeof(edge[1]),comp);
int k;
for(k=1;k<=E;++k)
{
if(findfather(edge[k].x)!=findfather(edge[k].y))
{
if(edge[k].x==dex&&edge[k].y==dey)
{continue;}
if(edge[k].x==dey&&edge[k].x==dex)
{continue;}
sum+=edge[k].dis;
Union(edge[k].x,edge[k].y);
}
}
returnsum;
}
bool Judge(int V) //判断图是否连通,不连通则无法构造最小生成树
{
for(int m=1;m<=V-1;++m)
if(findfather(m)!=findfather(m+1))
returnfalse;
returntrue;
}
int main()
{
inttest,j,V,E;
scanf("%d",&test);
while(test--)
{
scanf("%d%d",&V,&E);
num=0;
for(j=1;j<=E;++j)
{
scanf("%d%d%d",&edge[j].x,&edge[j].y,&edge[j].dis);
}
qsort(edge+1,E,sizeof(edge[1]),comp);
Init(V);
intsum=Krusual(V,E);
intM=1000,temp;
for(int q=1;q<=num;++q)
{
dex=edge1[q].x;
dey=edge1[q].y;
temp=AKrusual(V,E);
if(temp<M&&Judge(V))
M=temp;
if(M==sum) break;
}
if(M==sum) printf("Yes\n");
elseprintf("No\n");
}
}
---------------------------------------------------------------------------------
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=505;
int map[maxn][maxn];
bool vis[maxn];
int low[maxn];
int mst[maxn][maxn],pre[maxn];
bool inmst[maxn][maxn];
int n,m;
void init()
{
memset(map,inf,sizeof(map));
for(inti=1;i<=n;++i)
{
map[i][i]=0;
}
}
void slove()
{
intmincost=0;
intnext,Min;
memset(inmst,0,sizeof(inmst));
memset(mst,0,sizeof(mst));
for(inti=1;i<=n;++i)
{
low[i]=map[1][i];
vis[i]=0;
pre[i]=1;
}
vis[1]=1;
for(inti=2;i<=n;++i)
{
Min=inf;next=-1;
for(intj=1;j<=n;++j)
{
if(!vis[j]&&Min>low[j])
{
next=j;
Min=low[j];
}
}
mincost+=Min;
vis[next]=1;
intfa=pre[next];
inmst[next][fa]=inmst[fa][next]=1;
for(intj=1;j<=n;++j)
{
if(vis[j]&&j!=next)
{
mst[j][next]=mst[next][j]=max(mst[fa][j],low[next]);
}
if(!vis[j]&&low[j]>map[next][j])
{
low[j]=map[next][j];
pre[j]=next;
}
}
}
for(inti=1;i<=n;++i)
{
for(intj=1;j<i;++j)
{
if(map[i][j]!=inf&&!inmst[i][j])
{
if(map[i][j]==mst[i][j])
{
printf("Yes\n");
return;
}
}
}
}
printf("No\n");
}
int main()
{
intt;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
init();
for(inti=1;i<=m;++i)
{
inta,b,c;
scanf("%d%d%d",&a,&b,&c);
map[a][b]=map[b][a]=min(map[a][b],c);
}
slove();
}
return0;
}
#include<iostream>
using namespace std;
int n, mid;
int Partition(int arr[], int low, int high)
{
inti, j, pivot;
i= low, j = high, pivot = arr[low];
while(i< j)
{
while(i< j && arr[j] >= pivot) --j;
if(i< j)
swap(arr[i++],arr[j]);
while(i< j && arr[i] <= pivot) ++i;
if(i< j)
swap(arr[i],arr[j--]);
}
returnj; //返回基准元素位置
}
void Quick_Sort(int arr[], int low, int high)
{
intpivotpos;
if(low<= high)
{
pivotpos= Partition(arr, low, high);
if(pivotpos> n / 2)
Quick_Sort(arr,low, pivotpos - 1); //基准左递归排序
elseif(pivotpos < n / 2)
Quick_Sort(arr,pivotpos + 1, high); //基准右递归排序
else
mid= arr[pivotpos];
}
}
int main()
{
intcount = 0;
printf("输入数组元素的个数:");
scanf("%d",&n);
int*a = new int[n];
for(inti = 0; i < n; ++i)
scanf("%d",&a[i]);
Quick_Sort(a,0, n - 1);
for(inti = 0; i < n; ++i)
if(a[i]== mid)
count++;
printf(count> n / 2 ? "Yes\n" : "No\n");
deletea;
return0;
}
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int N = 10;
int arr[N];
/******************快速排序稳定版本*************************************/
void QuickSort(int low, int high)
{
if(low>= high)
return;
inti, j, pivot;
i= low, j = high, pivot = arr[(high + low) >> 1]; //每次取中间元素作为基准
swap(arr[low],arr[(high + low) >> 1]);
while(i< j)
{
while(i< j && arr[j] >= pivot) --j;
arr[i]= arr[j];
while(i< j && arr[i] <= pivot) ++i;
arr[j]= arr[i];
}
arr[i]= pivot;
QuickSort(low,i - 1); //递归左边
QuickSort(j+ 1, high); //递归右边
}
/*************************************************************************/
/******************快速排序一般版本(可求第K大元素)*****************/
int Partition(int low, int high)
{
inti, j, pivot;
i= low, j = high, pivot = arr[low];
while(i< j)
{
while(i< j && arr[j] >= pivot) --j;
if(i< j) swap(arr[i++], arr[j]);
while(i< j && arr[i] <= pivot) ++i;
if(i< j) swap(arr[i], arr[j--]);
}
returnj; //返回基准元素位置
}
void Quick_Sort(int low, int high)
{
intpivotpos;
if(low< high)
{
pivotpos= Partition(low, high);
Quick_Sort(low,pivotpos - 1); //基准左递归排序
Quick_Sort(pivotpos+ 1, high); //基准右递归排序
}
}
int select(int low, int high, int k)
{
intpivotpos, num;
if(low== high)
returnarr[high];
pivotpos= Partition(low, high);
num= pivotpos - low + 1; //左边元素个数
if(k== num)
returnarr[pivotpos];
elseif(k < num)
returnselect(low, pivotpos - 1, k);
else
returnselect(pivotpos + 1, high, k - num);
}
/*************************************************************************/
int main()
{
intk;
cout<<"输入10个数字:"<<endl;
for(inti = 0; i < 10; ++i)
scanf("%d",&arr[i]);
QuickSort(0,9);
cout<<"快速排序后:"<<endl;
for(inti = 0; i < 10; ++i)
cout<<arr[i]<<"";
cout<<endl;
cout<<"输入第K大元素:"<<endl;
cin>>k;
cout<<select(0,9, k)<<endl;
return0;
}
int pre[1010]; //存放第i个元素的父节点
int unionsearch(int root) //查找根结点
{
intson, tmp;
son= root;
while(root!= pre[root]) //寻找根结点
root= pre[root];
while(son!= root) //路径压缩
{
tmp= pre[son];
pre[son]= root;
son= tmp;
}
returnroot;
}
void join(int root1, int root2) //判断是否连通,不连通就合并
{
intx, y;
x= unionsearch(root1);
y= unionsearch(root2);
if(x!= y) //如果不连通,就把它们所在的连通分支合并
pre[x]= y;
}
int lowbit(int n) //计算res数组中第n个位置掌管的元素个数
{
returnn & (-n);
//returnn&(n^(n-1)); //结果同上
}
void add(int i, int plus) //将第i个元素增加plus(更新)
{
while(i<= N)
{
res[i]+= plus;
i+= lowbit(i); //只更新与之关联的res数组元素
}
}
int sum(int n) //求前n项的和
{
intresult = 0;
while(n> 0)
{
result+= res[n];
n-= lowbit(n); //只加上范围最大的res数组元素
}
returnresult;
}
int binarysearch(int arr[], int n, int key)
{
intlow = 0, high = n;
while(low< high)
{
intmid = low + (high - low) / 2;
if(arr[mid]== key)
{
cout<<"fad";
returnmid;
}
elseif(arr[mid] > key)
high= mid;
else
low= mid + 1;
}
return-1;
}
输入数据有多组,每组的第一行是公交车的总数N(0<=N<=10000);
第二行有徐总的所在地start,他的目的地end;
接着有n行,每行有站名s,站名e,以及从s到e的时间整数t(0<t<100)(每个地名是一个长度不超过30的字符串)。
note:一组数据中地名数不会超过150个。
如果N==-1,表示输入结束。
Output
如果徐总能到达目的地,输出最短的时间;否则,输出“-1”。
Sample Input
6
xiasha westlake
xiasha station 60
xiasha ShoppingCenterofHangZhou 30
station westlake 20
ShoppingCenterofHangZhou supermarket 10
xiasha supermarket 50
supermarket westlake 10
-1
#include<iostream>
#include<map>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int dis[155], len[155][155];
bool visit[155];
#define MAX 0x3f3f3f3f
void Dijsktra(int start, int end)
{
intk, temp;
memset(visit,0, sizeof(visit));
for(inti = start; i <= end; ++i)
dis[i]= (i == start ? 0 : MAX); //visit[start] = 1; //如果标记为1,则与temp比较的全都是MAX
for(inti = start; i <= end; ++i)
{
temp= MAX;
for(intj = start; j <= end; ++j)
if(!visit[j]&& dis[j] < temp)
temp= dis[k = j];
visit[k]= 1;
if(temp== MAX) break;
for(intj = start; j <= end; ++j)
if(dis[j]> dis[k] + len[k][j])
dis[j]= dis[k] + len[k][j];
}
}
int main()
{
intnum, iterator, distance, flag;
charbegin[30], end[30];
chara[30], b[30];
map<string,int> station;
while(scanf("%d",&num) != EOF && num != -1)
{
station.clear();
memset(len,MAX, sizeof(len));
flag= 0;
scanf("%s%s",begin, end);
if(strcmp(begin,end) == 0) flag = 1;
station[begin]= 1;
station[end]= 2;
iterator= 3;
for(inti = 0; i < num; ++i)
{
scanf("%s%s%d",a, b, &distance);
if(!station[a])
station[a]= iterator++;
if(!station[b])
station[b]= iterator++;
len[station[a]][station[b]]= len[station[b]][station[a]] = distance;
}
if(flag)
{
printf("0\n");
continue;
}
Dijsktra(1,iterator);
if(dis[2]== MAX) printf("-1\n");
else printf("%d\n", dis[2]);
}
return0;
}
22、最短路径 求最短距离
现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。
Input
N(v)和M(e)(0<N<200,0<M<1000),分别代表现有城镇的数目和已修建的道路的数目。城镇分别以0~N-1编号。
接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B<N,A!=B,0<X<10000),表示城镇A和城镇B之间有一条长度为X的双向道路。
再接下一行有两个整数S,T(0<=S,T<N),分别代表起点和终点。
Output
对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从S到T的路线,就输出-1.
Sample Input
3 3
0 1 1
0 2 3
1 2 1
0 2
3 1
0 1 1
1 2
Sample Output
2
-1
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define N 210
#define MAX 9999999
#define CLR(arr, what) memset(arr, what, sizeof(arr))
int num, road;
int dis[N], maze[N][N];
bool visit[N];
void Dijkstra(int start)
{
int temp, k;
CLR(visit,false);
for(int i = 0; i< num; ++i)
dis[i] = (i== start ? 0 : maze[start][i]);
visit[start] =true;
for(int i = 0; i< num; ++i)
{
temp = MAX;
for(int j =0; j < num; ++j)
if(!visit[j]&& temp > dis[j])
temp =dis[k = j];
if(temp ==MAX)
break;
visit[k] =true;
for(int j =0; j < num; ++j)
if(!visit[j]&& dis[j] > dis[k] + maze[k][j])
dis[j]= dis[k] + maze[k][j];
}
}
int main()
{
int a, b, cost,start, end;
while(scanf("%d%d", &num, &road) != EOF)
{
for(int i =0; i < N; ++i)
for(int j= 0; j < N; ++j)
maze[i][j]= MAX;
for(int i =0; i < road; ++i)
{
scanf("%d%d%d", &a, &b, &cost);
if(cost< maze[a][b]) //一条路可以有多个cost,记录最小的。注意
maze[a][b] = maze[b][a] = cost;
}
scanf("%d%d", &start, &end);
Dijkstra(start);
if(dis[end]== MAX)
printf("-1\n");
else
printf("%d\n",dis[end]);
}
return 0;
}
6(6条路) 2(和草家相邻城市个数) 3(想去城市的个数)
1 3 5
1 4 7
2 8 12
3 8 4
4 9 12
9 10 2
1 2(和草家相邻)
8 9 10(想去)
输出草儿能去某个喜欢的城市的最短时间
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
usingnamespace std;
#define MAX0x3f3f3f3f
int road,link, want, total;
intmap[1010][1010], linkarr[1010], wantarr[1010], dis[1010];
boolvisit[1010];
voidDijkstra(int start)
{
int temp, k;
memset(visit, 0, sizeof(visit));
for(int i = 1; i <= total; ++i)
dis[i] = map[start][i];
dis[start] = 0;
visit[start] = 1;
for(int i = 1; i <= total; ++i)
{
temp = MAX;
for(int j = 1; j <= total; ++j)
if(!visit[j] && temp >dis[j])
temp = dis[k = j];
visit[k] = 1;
for(int j = 1; j <= total; ++j)
if(!visit[j] && dis[j] >dis[k] + map[k][j])
dis[j] = dis[k] + map[k][j];
}
}
int main()
{
int x, y, cost, minn, answer;
while(scanf("%d%d%d", &road,&link, &want) != EOF)
{
total = 0;
memset(map, MAX, sizeof(map));
for(int i = 1; i <= road; ++i)
{
scanf("%d%d%d", &x,&y, &cost);
if(cost < map[x][y])
map[x][y] = map[y][x] = cost;
total = max(total, max(x, y)); //错了N久。。。。因为没有给出点的个数。
}
for(int i = 1; i <= link; ++i) //相连的城市
scanf("%d",&linkarr[i]);
for(int i = 1; i <= want; ++i) //目的地
scanf("%d", &wantarr[i]);
answer = MAX;
for(int i = 1; i <= link; ++i)//linkarr数组中所有元素中到达目的地最短的路
{
Dijkstra(linkarr[i]);
minn = MAX;
for(int j = 1; j <= want; ++j)//linkarr[i]中可以到达的目的地中最短
if(dis[wantarr[j]] < minn)
minn = dis[wantarr[j]];
if(answer > minn)
answer = minn;
}
printf("%d\n", answer);
}
return 0;
}
2
V e
3 2
1 2 1
2 3 1
3 3
1 2 1
2 3 1
1 3 1
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
#define N 100
#define MAX 1<<28
int cost[N][N];
int flow[N], pre[N];
bool visit[N];
int n, m;
int BFS()
{
inttemp;
queue<int>q;
visit[1]= true;
memset(pre,-1, sizeof(pre));
memset(visit,false, sizeof(visit));
for(inti = 1; i <= n; ++i)
flow[i]= MAX;
q.push(1);
while(!q.empty())
{
temp= q.front();
q.pop();
if(temp== n)
break;
for(inti = 1; i <= n; ++i) //寻找增广路最小流量
{
if(!visit[i]&& cost[temp][i] > 0)
{
visit[i]= true;
flow[i]= min(flow[temp], cost[temp][i]);
pre[i]= temp; //更新路径
q.push(i);
}
}
}
if(!visit[n]|| n == 1) //找不到完整增广路or源点汇点重合
return-1;
else
returnflow[n];
}
int EK()
{
inttemp, d, res, maxflow;
maxflow= 0;
while((d = BFS() ) != -1)
{
maxflow+= d;
temp= n;
while(temp!= 1)
{
res= pre[temp];
cost[res][temp]-= d; //正向边
cost[temp][res]+= d; //反向边
temp= res;
}
}
returnmaxflow;
}
int main()
{
intncase, T = 1;
intstart, end, capacity;
scanf("%d",&ncase);
while(ncase--)
{
memset(cost,0, sizeof(cost));
// v e
scanf("%d%d", &n, &m);
for(inti = 1; i <= m; ++i)
{
scanf("%d%d%d",&start, &end, &capacity); //重边叠加
cost[start][end]+= capacity;
}
printf("Case%d: %d\n", T++, EK());
}
return0;
}
本题目包含多组测试,请处理到文件结束。
在每个测试的第一行,有两个正整数 N 和 M ( 0<N<=200000,0<M<5000 ),分别代表学生的数目和操作的数目。
学生ID编号分别从1编到N。
第二行包含N个整数,代表这N个学生的初始成绩,其中第i个数代表ID为i的学生的成绩。
接下来有M行。每一行有一个字符 C (只取‘Q‘或‘U‘) ,和两个正整数A,B。
当C为‘Q‘的时候,表示这是一条询问操作,它询问ID从A到B(包括A,B)的学生当中,成绩最高的是多少。
当C为‘U‘的时候,表示这是一条更新操作,要求把ID为A的学生的成绩更改为B。
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define lson l, m, root << 1
#define rson m + 1, r, root << 1 | 1
const int N = 200010;
int segtree[N << 1 + 10]; //开2倍
void PushUp(int root) //节点保存区间最大值
{
segtree[root]= max(segtree[root << 1], segtree[root << 1 | 1]);
}
void Build_Tree(int l, int r, int root)
{
if(l ==r)
{
scanf("%d",&segtree[root]);
return;
}
int m =(l + r) >> 1;
Build_Tree(lson);
Build_Tree(rson);
PushUp(root);
}
void Update(int pos, int data, int l, int r, introot)
{
if(l ==r)
{
segtree[root]= data;
return;
}
int m =(l + r) >> 1;
if(pos<= m)
Update(pos,data, lson);
else
Update(pos,data, rson);
PushUp(root);
}
int Query(int L, int R, int l, int r, int root)
{
int sum= -9999999;
if(L<= l && r <= R)
returnsegtree[root];
int m =(l + r) >> 1;
if(L<= m)
sum= max(sum, Query(L, R, lson));
if(R> m)
sum= max(sum, Query(L, R, rson));
returnsum;
}
int main()
{
intnum, que;
charope;
int a,b;
while(scanf("%d%d",&num, &que) != EOF)
{
Build_Tree(1,num, 1);
for(inti = 0; i < que; ++i)
{
scanf("%*c%c%d %d", &ope, &a, &b);
if(ope== ‘U‘)
Update(a,b, 1, num, 1);
else
printf("%d\n",Query(a, b, 1, num, 1));
}
}
return0;
}
V e
4 5
1 2 3
2 3 4
3 4 5
1 4 10
1 3 12
#include <stdio.h>
#include <string.h>
#define Maxsize 20
#define FindMin(a,b) a>b?b:a
#define INF 999999999
int g[Maxsize][Maxsize];
int degree[Maxsize];
int count;
int v[Maxsize];
int ans;
int T;
void dfs(int u,int value)
{
inti,j;
if(u==T)
{
ans=FindMin(value,ans);
// printf("%d%d\n",value);
}
for(i=0;i<count;i++)
{
if(!((u>>i)&1))
{
for(j=i+1;j<count;j++)
if(!((u>>j)&1))
{
intnext=u;
next=next|(1<<i);
next=next|(1<<j);
dfs(next,value+g[v[i]][v[j]]);
}
}
}
}
int main()
{
intn,m;
intu,e,l;
inti,j,k;
intsum=0;
while(~scanf("%d%d",&n,&m))
{
memset(degree,0,sizeof(degree));
for(i=0;i<=n;i++)
for(j=0;j<=n;j++)
g[i][j]=INF;
sum=0;
while(m--)
{
scanf("%d%d%d",&u,&e,&l);
sum+=l;
degree[u]++;degree[e]++;
g[u][e]=g[e][u]=FindMin(g[u][e],l);
}
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
g[i][j]=FindMin(g[i][j],g[i][k]+g[k][j]);
count=0;
for(i=1;i<=n;i++)
if(degree[i]&1)
v[count++]=i;
T=0;
for(i=0;i<count;i++)
{
T=(T<<1)|1;
}
ans=INF;
dfs(0,0);
printf("%d\n",sum+ans);
}
return0;
}
3(苹果个数) 3(c)
Wv
1 1
2 1
3 1
0 0
求出能放入背包的苹果的总价钱最大值。
#include<stdio.h>
#include<string.h>
int max(int k,int m)
{return k>m?k:m;}
int dp[1010];
main()
{
int n,v,i,j;
while(scanf("%d%d",&n,&v),n&&v)
{
memset(dp,0,sizeof(dp));//此函数包含在string头文件里
int c,w;
for(i=1;i<=n;i++)
{
scanf("%d%d",&c,&w);
for(j=v;j>=c;j--)
{
dp[j]=max((dp[j-c]+w),dp[j]);
}
}
printf("%d\n",dp[v]);
}
}
4 (n个)5(c)
W v
2 3
1 2
3 4
2 2
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
int n,m;
int value[111];
int weight[111];
int dp[111111];
int V;
int main()
{
int i,j;
while(scanf("%d%d",&n,&m)!=EOF)
{
V=0;
for(i=1;i<=n;++i)
{
scanf("%d%d",&weight[i],&value[i]);
V+=value[i];
}
for(i=0;i<111111;++i)
{dp[i]=999999999;}
dp[0]=0; //<spanstyle="color:#339999;">//初始化价值为0的重量为0</span>
for(i=1;i<=n;++i)
{
for(j=V;j>=value[i];--j)
{
dp[j]=min(dp[j],dp[j-value[i]]+weight[i]);
}
}
for(i=V;i>=0;--i)
{
if(dp[i]<=m)
{printf("%d\n",i);break;}
}
}
return 0;
}
29、0-1背包
4(n) 5(c)
W v
2 3
1 2
3 4
2 2
#include <iostream>
#include <cstdio>
#include <cstring>
#define INF 0x3f3f3f3f
#define N 10010
usingnamespacestd;
intres[N],w[110],v[110];
intW,n;
intmain()
{
while(scanf("%d%d",&n,&W)!=EOF)
{
res[0]=0;
for(inti=1;i<N;i++)
res[i]=INF;
intsum=0;
for(inti=0;i<n;i++)
{
scanf("%d%d",&w[i],&v[i]);
sum+=v[i];
}
for(inti=0;i<n;i++)
{
for(intj=sum;j>=v[i];j--)
{
res[j]=min(res[j],res[j-v[i]]+w[i]);
}
}
for(inti=sum;i>=0;i--)
if(res[i]<=W)
{
printf("%d\n",i);
break;
}
}
return0;
}
标签:
原文地址:http://blog.csdn.net/gz153016/article/details/51459051