j=1.0/2就是1/2的意思
之所以1.0而不是1,是因为c++里除法如果都是整数会变成整除,结果是0,而不是0.5,所以要第一个数写成1.0
第一行为一个数 ,表示图中点的个数。
而后的 行都由 个被空格分隔的数组成,第 行第 列表示第 个点和第 个点没有联通的情况下,在这两个点之间构造一条边的代价(即这 行 列为矩阵 )。
而后为一个数 ,表示图中已经存在的边的数量。
而后的 行都由两个被空格分隔的数组成,分别是已经存在的边相连接的两个点 和 。
输出一个数,表示新增加的边的代价和。
样例1
input:
4
0 6692 8925 9679
6692 0 9526 656
8925 9526 0 2664
9679 656 2664 0
2
1 3
1 2
output:
656
#include <iostream>
using namespace std;
int find(int* p, int key)
{
int index = key;
while (p[index] != index)
{
index = p[index];
}
return index;
}
void allset(int* p, int n1, int n2)
{
int r1 = find(p, n1);
int r2 = find(p, n2);
if (r1 == r2)
return;
else
p[r1] = r2;
return;
}
void findmin(int** q, int n, int a[])
{
int min = q[0][0];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (q[i][j] < min)
{
min = q[i][j];
a[0] = i+1;
a[1] = j+1;
}
}
}
q[a[0] - 1][a[1] - 1] += 9999999;
}
int main()
{
int n;
cin >> n;
int* p = new int[n+1];
p[0] = 0;
for (int i = 1; i < n + 1; i++)
p[i] = i;
int** q = new int* [n];
for (int i = 0; i < n; i++)
q[i] = new int[n];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> q[i][j];
}
}
int m;
cin >> m;
int k1,k2 ;
for (int i = 0; i < m; i++)
{
cin >> k1 >> k2;
allset(p, k1, k2);
q[k1 - 1][k2-1] = 9999999;
}
for (int i = 0; i < n; i++)
q[i][i] = 9999999;
int k12[2];
int sum = 0;
while (m != n - 1)
{
findmin(q, n, k12);
if(find(p,k12[0])==find(p,k12[1]))
{
;
}
else
{
allset(p, k12[0], k12[1]);
m++;
sum += q[k12[0] - 1][k12[1] - 1] - 9999999;
}
}
cout <<sum;
return 0;
}
17
total submissions: 752times
passed: 334times
passing rate: 44.41%
memory limit: 10485760(BYTE)
time limit: 1000(MS)
input limit: 1000(line)
output limit: 1000(line)
一个连通图中有 个点和 条边 ( > ) 。每条边都有对应的权值。题目需要你删除权值较大的边以消除多余的边,同时保证图的连通性。最终输出所有被删除的边的权值和。点的编号从1开始。
第一行两个正整数 和 ,分别代表点的数量和边的数量。
之后 行每行有三个整数 分别表示边的两段端点序号和边的权值。
输出一个正整数,代表所有被删除边的权值和。
样例1
input:
5 5
1 2 8
1 3 1
1 5 3
2 4 5
3 4 2
output:
8
#include<iostream>
using namespace std;
int findmin(int**a,int m)
{
int k = a[0][2];
int ki=0;
for (int i = 0; i < m; i++)
{
if (a[i][2] < k)
{
k = a[i][2];
ki = i;
}
}
a[ki][2] += 1000;
return ki;
}
int find(int* p, int key)
{
int index = key;
while (p[index] != index)
{
index = p[index];
}
return index;
}
bool unionset(int* p, int n1, int n2)
{
int r1 = find(p, n1);
int r2 = find(p, n2);
if (r1 == r2)
return false;
else
{
p[r2] = p[r1];
}
return true;
}
int main()
{
int n, m;
cin >> n >> m;
int* p = new int[n+1];
p[0] = 0;
for (int i = 1; i < n+1; i++)
{
p[i] = i;
}
int** q = new int* [m];
for (int i = 0; i < m; i++)
{
q[i] = new int[3];
}
for (int i = 0; i < m; i++)
{
for (int j = 0; j < 3; j++)
{
cin >> q[i][j];
}
}
int tog = 0;
for (int i = 0; i < m; i++)
{
int x = findmin(q, m);
if (find(p, q[x][0]) == find(p, q[x][1]))
{
tog += q[x][2] - 1000;
}
else
{
unionset(p, q[x][0], q[x][1]);
}
}
cout << tog;
return 0;
}
18
total submissions: 1193times
passed: 353times
passing rate: 29.59%
memory limit: 10485760(BYTE)
time limit: 1000(MS)
input limit: 1000(line)
output limit: 1000(line)
一个有向图中有 个顶点和 条单向路径 , 请使用Dijkstra算法,求出某一个顶点到其他顶点的最短路径。
第一行两个正整数 和 ,分别代表点的数量和路径的数量。 1< <20, 0<= <50
之后 行每行有三个整数 分别表示 路径 的起点、终点序号和路径长度。顶点编号从1开始,0<i,j<=n,0<k<100
源点编号p ,0<p<=n
Ⅰ.Dijkstra计算过程;
Ⅱ.输出给定点v到其他各点的路径,以及最短距离。
注意输出格式。橘色点代表空格。CRLF代表换行。
按照Dijkstra算法获取最短路径顺序进行输出,如果没有路径则输出“No Path to ”【顶点编号,升序排列,中间使用空格隔开】
样例1
input:
8 10
1 6 10
1 5 5
6 3 1
6 5 2
3 4 4
4 1 7
4 3 6
5 6 3
5 3 9
5 4 2
1
output:
No.1 : 1 -> 5 , d = 5
No.2 : 1 -> 5 -> 4 , d = 7
No.3 : 1 -> 5 -> 6 , d = 8
No.4 : 1 -> 5 -> 6 -> 3 , d = 9
No.5 : No Path to 2 7 8
#include<iostream>
#include<stack>
using namespace std;
struct edge
{
int bg, ed, val;
edge(int p = 0,int q = 0,int v = -1):bg(p), ed(q), val(v){}
};
struct Node
{
int flag;//标示结点是否已被访问。
Node(int f = 0):flag(f){}
};
//存储距离该结点最近的点以及路径长
struct path
{
int length, k;
path(int l = 101,int kk = 0):length(l),k(kk){}
path(const path& p)
{
length = p.length;
k = p.k;
}
};
//得到距离该点最近的点的路径长度
int minpath(int bg, int ed, edge* e, int m)
{
if(bg == ed)return 0;
int min = 101;
for(int i = 0;i < m; i++)
if(e[i].bg == bg && e[i].ed == ed && e[i].val < min)
min = e[i].val;
return min;
}
int main()
{
int n, m, t1, t2, t3, s;
cin >> n >> m;
edge* e = new edge[m];
Node* N = new Node[n];
int* pre = new int[n];//与当前结点相连的前一个点。
path* p = new path[n];
for(int i = 0; i < n; i++)
p[i].k = i;
for(int i = 0; i < n; i++)
pre[i] = -1;
for(int i = 0; i < m; i++)
{
cin >> t1 >> t2 >> t3;
e[i].bg = t1 - 1;
e[i].ed = t2 - 1;
e[i].val = t3;
}
cin >> s;
s -= 1;
pre[s] = s;
p[s].length = 0;
N[s].flag = 1;
int* key = new int[n];
for(int i = 0; i < n; i++)
{
p[i].length = minpath(s, i, e, m);
key[i] = p[i].length;//暂存各结点的最短路径。
}
int c1, c2;
c1 = s;//从源点开始搜寻。
for(int i = 0; i < n - 1; i++)
{
for(int j = 0; j < n; j++)
{
if(N[j].flag == 1)continue;//已访问,直接跳到下一个结点。
if(key[j] > (key[c1] + minpath(c1, j, e, m)))
{
key[j] = key[c1] + minpath(c1, j, e, m);
pre[j] = c1;
}
}
int min = 101, j = 0;;
for(;j < n; j++)
{
if(N[j].flag == 1)continue;
if(key[j] <= min)
{
min = key[j];
c2 = j;
}
}
N[c2].flag = 1;
if(i == 0)pre[c2] = c1;
p[c2].length = key[c2];
c1 = c2;
}
for(int i = 0; i < n; i++)
for(int j = i + 1; j < n; j++)
if(p[j].length < p[i].length)
{
path pp = p[j];
p[j] = p[i];
p[i]= pp;
}
int count = 1, flag = 0;
for(int i = 0; i < n; i++)
{
int num = p[i].k;
if(p[i].k == s)continue;
if(p[i].length == 101)
{
flag++;
continue;
}
stack<int> st;
st.push(num);
while(pre[num] != s)
{
st.push(pre[num]);
num = pre[num];
}
cout << "No." << count++ << " : " << s + 1 << " ";
while(!st.empty())
{
cout << "-> " << st.top() + 1 << " ";
st.pop();
}
cout << ", d = " << p[i].length << endl;
}
if(flag > 0)
{
cout << "No." << count << " : No Path to";
int *np = new int[flag];
int q = 0;
for(int i = 0; i < n; i++)
{
if(p[i].length == 101) np[q++] = p[i].k + 1;
}
for(int i = 0;i < flag; i++)
for(int j = i + 1; j < flag; j++)
if(np[j] < np[i])
{
int tmp = np[j];
np[j] = np[i];
np[i] = tmp;
}
for(int i = 0; i < flag; i++)cout << " " << np[i];
}
return 0;
}
19
total submissions: 917times
passed: 350times
passing rate: 38.17%
memory limit: 10485760(BYTE)
time limit: 1000(MS)
input limit: 1000(line)
output limit: 1000(line)
一个有向图中有 个顶点和 条单向路径 , 试求任意两地点间最短距离。