//Kruskal算法
# include <iostream>
# include <set>
# define A first
# define B second
using namespace std;
int pre[103];
multiset<pair<int,pair<int,int> > >s;//set容器来对边权排序
int find(int x){return x==pre[x]?x:pre[x]=find(pre[x]);}//并查集路径压缩,找根节点
int main()
{
int n, u, v, w, m;
while(cin >> n >> m)//n个点m条边
{
s.clear();
int min_length=0;
for(int i=1; i<=n; ++i) pre[i] = i;
for(int i=0; i<m; ++i)//输入m条边
{
cin >> u >> v >> w;
s.insert({w,{u,v}});
}
for(auto it=s.begin(); it!=s.end() && n!=1; ++it)
{
int u = find(it->B.A), v = find(it->B.B);
if(u != v)//若两个节点属于不同的联通分量,就合并在一起
{
pre[u] = v;
--n;
min_length += it->A;
}
}
cout << min_length << '\n';
}
return 0;
}//prim算法
# include <iostream>
# include <cstring>
# include <queue>
# define pii pair<int,int>
# define A first
# define B second
using namespace std;
vector<pii >g[103];
int n, lowcost[103], min_length=0;
void prim()
{
int cnt = 0;
memset(lowcost, 0x3f, sizeof(lowcost));//初始化所有点的距离为无限大
priority_queue<pii, vector<pii >, greater<pii > >q;//优先队列优化,队列头为权值最小的边
q.push({0, 1});
while(1)
{
while(lowcost[q.top().B] == -1) q.pop();//若该点已经进入MST,就出队
int u = q.top().B, w = q.top().A;
q.pop();
min_length += w;
if(++cnt == n) break;
for(int i=0; i<g[u].size(); ++i)
{
int v = g[u][i].A, w = g[u][i].B;
if(lowcost[v] != -1 && w < lowcost[v])//更新其他点到MST的最短距离
{
lowcost[v] = w;
q.push({lowcost[v], v});
}
}
lowcost[u] = -1;//-1表示该点进入MST
}
}
int main()
{
int u, v, m, w;
while(cin >> n >> m)//n个点m条边
{
min_length=0;
for(int i=1; i<=n; ++i) g[i].clear();
for(int i=0; i<m; ++i)//输入m条边
{
cin >> u >> v >> w;
g[u].push_back({v,w});
g[v].push_back({u,w});
}
prim();
cout << min_length << '\n';
}
return 0;
}//随机生成10个点20条边的连通图程序
# include <bits/stdc++.h>
using namespace std;
struct node
{
int u, v, w;
}edge[20];//储存20条边
int pre[11], cnt=0;
int find(int x) {return x==pre[x]?x:pre[x]=find(pre[x]);}//并查集
int main()//对10个点随机生成20条边,且要连通图
{
srand(time(0));
for(int i=1; i<=10; ++i) pre[i] = i;
for(int i=0; i<9; ++i)//先用9条边生成一棵树
{
int u = rand()%10; ++u;
int v = rand()%10; ++v;
int pu = find(u), pv = find(v);
if(pu != pv)
{
pre[pu] = pv;
edge[cnt++] = {u, v, rand()%100};
}
else --i;
}
for(int i=0; i<11; ++i)//再随机生成剩下的11条边
{
int u = rand()%10; ++u;
int v = rand()%10; ++v;
edge[cnt++] = {u, v, rand()%100};
}
return 0;
}
1.有1,2,....一直到n的无序数组,求排序算法,并且要求时间复杂度为O(n),空间复杂度O(1),使用交换,而且一次只能交换两个数。
# include <stdio.h>
int main()
{
int a[10] = {8,7,5,4,1,6,3,9,10,2};
for(int i=0; i<10; ++i)
while(a[i] != i+1)
{
int t = a[i];
a[i] = a[t-1];
a[t-1] = t;
}
for(int i=0; i<10; ++i)
printf("%d ",a[i]);
return 0;
}
2.求一个字符串的最大回文前缀长度。回文是指正反方向读起来都一样的字符串,比如“abcdcba”就是一个回文。
# include <iostream>
# include <cstdio>
# include <cstring>
# include <algorithm>
# define ull unsigned long long
using namespace std;
char s[1000000];
int main()//Hash
{
while(~scanf("%s",s))
{
int len = strlen(s);
ull a=0, b=0, pow=1, seed=233, ans=0;
for(int i=0; i<len; ++i)
{
a = a + s[i]*pow;
pow *= seed;
b = b*seed + s[i];
if(a == b)
ans = max(ans, (ull)i+1);
}
printf("%llu\n",ans);
}
return 0;
}最小生成树kruskal和prim
//Kruskal
# include <iostream>
# include <set>
# define A first
# define B second
using namespace std;
int pre[103];
multiset<pair<int,pair<int,int> > >s;//set容器来对边权排序
int find(int x){return x==pre[x]?x:pre[x]=find(pre[x]);}//并查集路径压缩,找根节点
int main()
{
int n, u, v, w;
while(cin >> n,n)
{
s.clear();
int min_length=0;
for(int i=1; i<=n; ++i) pre[i] = i;
for(int i=0; i<n*(n-1)/2; ++i)//假设是完全图
{
cin >> u >> v >> w;
s.insert({w,{u,v}});
}
for(auto it=s.begin(); it!=s.end() && n!=1; ++it)
{
int u = find(it->B.A), v = find(it->B.B);
if(u != v)//若两个节点属于不同的联通分量,就合并在一起
{
pre[u] = v;
--n;
min_length += it->A;
}
}
cout << min_length << '\n';
}
return 0;
}//prim
# include <iostream>
# include <cstring>
# include <queue>
# define pii pair<int,int>
# define A first
# define B second
using namespace std;
vector<pii >g[103];
int n, lowcost[103], min_length=0;
void prim()
{
int cnt = 0;
memset(lowcost, 0x3f, sizeof(lowcost));//初始化所有点的距离为无限大
priority_queue<pii, vector<pii >, greater<pii > >q;//优先队列优化,队列头为权值最小的边
q.push({0, 1});
while(1)
{
while(lowcost[q.top().B] == -1) q.pop();//若该点已经进入MST,就出队
int u = q.top().B, w = q.top().A;
q.pop();
min_length += w;
if(++cnt == n) break;
for(int i=0; i<g[u].size(); ++i)
{
int v = g[u][i].A, w = g[u][i].B;
if(lowcost[v] != -1 && w < lowcost[v])//更新其他点到MST的最短距离
{
lowcost[v] = w;
q.push({lowcost[v], v});
}
}
lowcost[u] = -1;//-1表示该点进入MST
}
}
int main()
{
int u, v, w;
while(cin >> n,n)
{
min_length=0;
for(int i=1; i<=n; ++i) g[i].clear();
for(int i=0; i<n*(n-1)/2; ++i)//假设是完全图
{
cin >> u >> v >> w;
g[u].push_back({v,w});
g[v].push_back({u,w});
}
prim();
cout << min_length << '\n';
}
return 0;
}JAVA课设代码,临时存放
import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class Client extends JFrame implements ActionListener{
Socket sock;
JTextArea t1 = new JTextArea();
JTextField t2 = new JTextField(20);
JButton b1 = new JButton("send");
JButton b2 = new JButton("连接服务器");
DataOutputStream out;
DataInputStream in;
public Client() {
JScrollPane jsp = new JScrollPane(t1);
this.getContentPane().add(jsp, "Center");
JPanel p1 = new JPanel();
p1.add(t2);
p1.add(b1);
JPanel p2 = new JPanel();
p2.add(b2);
this.getContentPane().add(p2, "North");
this.getContentPane().add(p1, "South");
b1.addActionListener(this);
b2.addActionListener(this);
setTitle("客户端");
setSize(340,200);
setVisible(true);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
try {
out.writeUTF("bye");
}catch(Exception ee) {}
dispose();
System.exit(0);
}
});
}
public void actionPerformed(ActionEvent e) {
if(e.getSource()==b1) {
if(!t2.getText().equals("")) {
try {
out.writeUTF(t2.getText());
t1.append("客户说:"+t2.getText()+"\n");
}catch(Exception ee) {}
}
}
else {
try {
sock = new Socket("127.0.0.1",6000);
OutputStream os = sock.getOutputStream();
out = new DataOutputStream(os);
InputStream is = sock.getInputStream();
in = new DataInputStream(is);
Communion2 th = new Communion2(this);
th.start();
}catch(IOException ee) {
JOptionPane.showMessageDialog(null, "连接服务器失败");
return;
}
}
}
public static void main(String args[]) {
Client mainFrame = new Client();
}
}
class Communion2 extends Thread{
Client fp;
Communion2(Client fp){
this.fp = fp;
}
public void run() {
String msg = null;
while(true) {
try {
msg = fp.in.readUTF();
if(msg.equals("bye")) {
fp.t1.append("服务器已停止\n");
break;
}
fp.t1.append("服务器说:"+msg+"\n");
}catch(Exception ee) {break;}
}
try {
fp.out.close();
fp.in.close();
fp.sock.close();
}catch(Exception ee) {}
}
}import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class Server extends JFrame implements ActionListener {
ServerSocket s;
Socket sock;
JTextArea t1 = new JTextArea();
JTextField t2 = new JTextField(20);
JButton b1 = new JButton("send");
DataOutputStream out;
DataInputStream in;
String cname = null;
public Server() {
try {
s = new ServerSocket(6000);
}catch(IOException e) {
JOptionPane.showMessageDialog(null, "服务器启动失败!");
return;
}
JScrollPane jsp = new JScrollPane(t1);
this.getContentPane().add(jsp,"Center");
JPanel p1 = new JPanel();
p1.add(t2);
p1.add(b1);
this.getContentPane().add(p1, "South");
b1.addActionListener(this);
setTitle("服务器");
setSize(340,200);
setVisible(true);
try {
sock = s.accept();
out = new DataOutputStream(sock.getOutputStream());
in = new DataInputStream(sock.getInputStream());
out.writeUTF("你的服务器连接成功");
Communion th = new Communion(this);
th.start();
}catch(Exception e) {}
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
try {
out.writeUTF("bye");
}catch(Exception ee) {}
dispose();
System.exit(0);
}
});
}
public void actionPerformed(ActionEvent e) {
if(!t2.getText().equals("")) {
try{
out.writeUTF(t2.getText());
t1.append("服务器说:"+t2.getText()+"\n");
}catch(Exception ee) {}
}
}
public static void main(String args[]) {
Server mainFrame = new Server();
}
}
class Communion extends Thread{
Server fp;
Communion(Server fp){
this.fp = fp;
}
public void run() {
String msg = null;
while(true) {
try {
msg = fp.in.readUTF();
if(msg.equals("bye")) {
fp.t1.append("客户已经退出\n");
break;
}
fp.t1.append("客户说:"+msg+"\n");
}catch(Exception ee) {break;}
}
try {
fp.out.close();
fp.in.close();
fp.sock.close();
fp.s.close();
}catch(Exception ee) {}
}
}
# include <iostream>//请用文件输入输出
# include <cstring>
# include <cstdio>
# include <list>
using namespace std;
struct node
{
string key;//英文
list<string>la;//拉丁文
node *parent;//父节点
node *right;//右儿子
node *left;//左儿子
};
void insert(node** root, string key, string La)//插入单词,根节点用指针的指针,因为需要修改指针的值。
{
node *p = new node;//定义一个新节点。
p->key = key;//填入信息
p->la.push_back(La);//填入信息
p->left = p->right = p->parent = NULL;//初始化
if(*(root) == NULL)//若根节点为空
{
*root = p;
return;
}
if((*root)->left == NULL && key < (*root)->key)//若左儿子为空(string可以直接按字典序比较)
{
p->parent = *root;
(*root)->left = p;
return;
}
if((*root)->right == NULL && key > (*root)->key)//若右儿子为空
{
p->parent = *root;
(*root)->right = p;
return;
}
delete p;
if(key <(*root)->key)//否则,进入相应的儿子。
insert(&(*root)->left, key, La);
else if(key > (*root)->key)
insert(&(*root)->right, key, La);
else
(*root)->la.push_back(La);//★若英语单词已经存在,直接更新它的拉丁字母链表。
}
void in_order_walk(node *p)//中序遍历,模拟字典序输出
{
if(p == NULL) return;
if(p->left != NULL) in_order_walk(p->left);
cout << p->key << ":";
int cnt = 0;
for(list<string>::iterator it=p->la.begin(); it != p->la.end(); ++it,++cnt)
cout << *it << (cnt==p->la.size()-1?'\n':',');
if(p->right != NULL)
in_order_walk(p->right);
}
int main()
{
//freopen("input.txt", "r", stdin);
//freopen("output.txt","w",stdout);
string s, unit;
getline(cin, s);
node * root;
while(s[0] == '%')
{
unit = s;
root = NULL;
string t;
while(getline(cin, t) && t[0]!='%')//如果t[0]=='&'或者到达文件尾说明上一个Unit输入完毕,输出上一个Unit的二叉树。
{
int pos = t.find(":");
string La = t.substr(0, pos), key;//提取拉丁字母
for(int i=pos+1,j; i<t.length();)
{
for(j=i; j<=t.length()&&t[j]!=','; ++j);
key = t.substr(i, j-i);//提取英文单词
i = j+1;
insert(&root, key, La);
}
}
s = t;
cout << unit <<endl;
in_order_walk(root);
cout <<endl;
}
return 0;
}
# include <iostream>
# include <cstdio>
using namespace std;
int* home[1<<10];//索引的范围为1024(二进制10000000000),保存桶的指针。
int tong[1<<10][22];//每个桶能储存20个数,其中第21个数是该桶的深度。
int dep = 0, id=0;//dep是目录索引的深度,id是桶的编号
inline int get(int x, int deep)//返回x数值二进制的最低deep位数字。
{
int res = 0;
for(int i=0; i<=deep; ++i)
if(x&(1<<i)) res |= (1<<i);
return res;
}
bool query(int x)
{
int key = get(x, dep);
int* p = home[key];
for(int i=1; i<=p[0]; ++i)//遍历这个桶看在不在里面
if(p[i] == x) return true;
return false;
}
void delet(int x)
{
if(!query(x)) return;
int key = get(x, dep);
int* p = home[key];
for(int i=1; i<=p[0]; ++i)
{
if(p[i] == x)
{
for(int j=i+1; j<=p[0]; ++j)//后面的数全部左移,桶只有20容量,能保证高效率
p[j-1] = p[j];
--p[0];
return;
}
}
}
bool insert(int x)
{
if(query(x)) return true;//如果该数已经在哈希表中就结束。
int key = get(x, dep);//获取索引值
int* p = home[key], *t1=0, *t2=0;
if(p[0] < 20) p[++p[0]] = x;//如果桶还有空位就加进去
else
{
int cur_dep = p[21], old_key = get(p[1], cur_dep);
t1 = tong[id++];//建立新桶t1
t1[21] = cur_dep+1;
t2 = tong[id++];//建立新桶t2
t2[21] = cur_dep+1;
int tmp[21]={0};
for(int i=1; i<=20; ++i) tmp[i] = p[i];
p[0] = 0;
for(int i=1; i<=20; ++i)
{
int cur = get(tmp[i], cur_dep+1);//将桶内原有元素的增高一位的索引提取出来,下同。
if(cur == old_key) t1[++t1[0]] = tmp[i];//如果高位是0就加到t1桶。
else t2[++t2[0]] = tmp[i];//如果高位是1就加到t2桶。
}
if(cur_dep+1 <= dep)//如果桶的深度没有超过目录索引的深度
{
for(int i=0; i<(1<<dep+1); ++i)//更新指向p桶的指针,根据高位是否1判断
{
int cur_key = get(i, cur_dep+1);
if(cur_key == old_key) home[i] = t1;
else if(cur_key == (old_key|(1<<cur_dep+1))) home[i] = t2;
}
}
else//如果超过了
{
++dep;
for(int i=0; i<(1<<(dep+1)); ++i)//要更新所有索引
{
int cur_key = get(i, cur_dep+1);
if(cur_key == old_key) home[i] = t1;
else if(cur_key == (old_key|(1<<cur_dep+1))) home[i] = t2;
else if(i&(1<<dep)) home[i] = home[i^(1<<dep)];//高位是1的跟高位是0指向同一个桶
}
}
return false;//暂时插入失败,返回false
}
return true;//插入成功
}
void output()
{
freopen("output.txt","w",stdout);//输出到文件
for(int i=0; i<id; ++i)//将所有桶的元素输出到文件
for(int j=1; j<=tong[i][0]; ++j)
cout << tong[i][j] <<endl;
freopen("CON","w",stdout);//重定向到控制台输出
}
int main()
{
int n, m, x;
cout << "请输入操作次数N:";
cin >> n;
tong[id][21] = 0;
home[0] = tong[id++];
tong[id][21] = 0;
home[1] = tong[id++];//初始拥有0和1两个索引的桶。
cout << "操作类型: \n1 X表示插入X\n2 X表示查询X\n3 X表示删除X\n4 X表示将所有数导出到文件。" <<endl;
while(n--)
{
cin >> m >> x;
if(m == 1)
while(!insert(x));//此处插入X先将桶的容量分配好,所以一次插入未必成功,要循环多次。
else if(m == 2)
{
if(query(x)) puts("YES");
else puts("NO");
}
else if(m == 3)
delet(x);
else
output();
}
return 0;
}
int pre[maxn],low[maxn],bccno[maxn],dfs_clock,bcc_cnt;
stack<int>S;
vector<int>ans;
vector<PII >G[maxn];
void dfs(int u,int fa) {
low[u]=pre[u]=++dfs_clock;
dad[u]=fa;
S.push(u);
int k=0;
for(int i=0; i<G[u].size(); ++i)
{
int v=G[u][i].first;
if(v==fa && !k)
{
++k;
continue;
}
if(!pre[v]) dfs(v,u);
low[u]=min(low[u],low[v]);
}
if(pre[u]==low[u])
{
++bcc_cnt;
int tmp;
do
{
tmp=S.top();
S.pop();
bccno[tmp]=bcc_cnt;
}while(u!=tmp);
}
}
int main()
{
int n, m, u, v;
while(~scanf("%d%d",&n,&m))
{
ans.clear();
for(int i=0; i<=n; ++i) G[i].clear();
dfs_clock = bcc_cnt = 0;
memset(pre, 0, sizeof(pre));
memset(low, 0, sizeof(low));
for(int i=0; i<m; ++i)
{
scanf("%d%d",&u,&v);
G[u].pb(mp(v,i));
G[v].pb(mp(u,i));
}
for(int i=0; i<n; i++)
if(!pre[i])dfs(i,i);
}
return 0;
}
# include <iostream>
# include <cstdio>
# include <cmath>
typedef long long LL;
LL a[11], mod[11], n;
int T, m;
LL Exgcd(LL a,LL b,LL &x,LL &y)
{
if (!b)
{
x=1;y=0;
return a;
}
LL d=Exgcd(b,a%b,x,y);
LL t=x;
x=y;
y=t-(a/b)*y;
return d;
}
LL CRT()
{
for(int i=2; i<=m; ++i)
{
LL x=0,y=0;
LL c=a[i]-a[1],d=Exgcd(mod[1],mod[i],x,y);
if (c%d) return 0;
x*=(c/d);
x=((x%mod[i])+mod[i])%mod[i];
a[1]=mod[1]*x+a[1];
mod[1]=mod[1]/d*mod[i];
a[1]=a[1]%mod[1];
}
if(a[1] > n) return 0;
LL temp = (n-a[1])/mod[1]+(a[1] != 0);
return temp;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%lld%d",&n,&m);
for(int i=1; i<=m; ++i) scanf("%lld",&mod[i]);
for(int i=1; i<=m; ++i) scanf("%lld",&a[i]);
printf("%lld\n",CRT());
}
}
# include <iostream>
# include <cstdio>
# include <cmath>
# include <cstring>
# include <algorithm>
using namespace std;
const int maxn = 2003;
int n;
struct node{double x, y;}a[maxn], ans[maxn];
inline node operator-(node a, node b)
{
return node{a.x-b.x, a.y-b.y};
}
inline double operator*(node a, node b)
{
return a.x*b.y - a.y*b.x;
}
inline double dis(node a)
{
return a.x*a.x+a.y*a.y;
}
inline bool cmp(node x, node y)
{
if(fabs((x-a[1])*(y-a[1]))>0) return (x-a[1])*(y-a[1])>0;
return dis(x-a[1])<dis(y-a[1]);
}
inline double cha(node a, node b, node c)
{
return fabs((a-b)*(a-c))/2;
}
int main()
{
scanf("%d",&n);
for(int i=1; i<=n; ++i) scanf("%lf%lf",&a[i].x,&a[i].y);
for(int i=2;i<=n;i++)
if(a[i].y<a[1].y||(a[i].y==a[1].y&&a[i].x<a[1].x))
swap(a[1],a[i]);
sort(a+2,a+n+1,cmp);
int top=2;ans[1]=a[1];ans[2]=a[2];
for(int i=3; i<=n; ++i)
{
while(top>1&&(a[i]-ans[top-1])*(ans[top]-ans[top-1])>=0) --top;
ans[++top]=a[i];
}
for(int i=0;i<top;i++)
ans[i] = ans[i+1];
n=top;
double imax = 0;
for(int i=0;i<n-2;i++)
{
int ti=(i+3)%n, tj=(i+1)%n;
for(int j=i+2; j<n; ++j)
{
while(cha(ans[i],ans[j],ans[ti]) < cha(ans[i],ans[j],ans[(ti+1)%n])) ti=(ti+1)%n;
while(cha(ans[i],ans[j],ans[tj]) < cha(ans[i],ans[j],ans[(tj+1)%n])) tj=(tj+1)%n;
imax = max(imax, cha(ans[i],ans[j],ans[ti])+cha(ans[i],ans[j],ans[tj]));
}
}
printf("%.3f",imax);
return 0;
}
本文深入探讨了图算法中的Kruskal和Prim最小生成树算法,详细讲解了算法原理及其实现过程,并提供了完整的代码示例。此外,还介绍了生成随机连通图的方法、高效排序算法、字符串最大回文前缀查找算法等实用技巧。
69

被折叠的 条评论
为什么被折叠?



