无题(updating)

本文深入探讨了图算法中的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, 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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值